blob: 83781c475af32ca6cc93e16e4e441b9ec409e6d4 [file]
{"version":"1.0","encoding":"UTF-8","feed":{"xmlns":"http://www.w3.org/2005/Atom","xmlns$openSearch":"http://a9.com/-/spec/opensearch/1.1/","xmlns$batch":"http://schemas.google.com/gdata/batch","xmlns$gd":"http://schemas.google.com/g/2005","xmlns$gs":"http://schemas.google.com/spreadsheets/2006","xmlns$thr":"http://purl.org/syndication/thread/1.0","xmlns$sites":"http://schemas.google.com/sites/2008","xmlns$dc":"http://purl.org/dc/terms","xmlns$gAcl":"http://schemas.google.com/acl/2007","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev"},"updated":{"$t":"2021-09-16T14:50:05.859Z"},"title":{"$t":"Content"},"link":[{"rel":"alternate","type":"text/html","href":"https://sites.google.com/feeds/content/chromium.org/dev"},{"rel":"next","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev?alt\u003djson\u0026start-index\u003d2001\u0026max-results\u003d500"},{"rel":"http://schemas.google.com/g/2005#feed","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev"},{"rel":"http://schemas.google.com/g/2005#post","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev"},{"rel":"http://schemas.google.com/g/2005#batch","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/batch"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev?alt\u003djson\u0026start-index\u003d1501\u0026max-results\u003d500"},{"rel":"previous","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev?alt\u003djson\u0026start-index\u003d1000\u0026max-results\u003d501"}],"generator":{"version":"1","uri":"https://sites.google.com","$t":"Google Sites"},"openSearch$startIndex":{"$t":"1501"},"openSearch$itemsPerPage":{"$t":"500"},"entry":[{"gd$etag":"\"XCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8386826802801315030"},"published":{"$t":"2011-06-28T07:24:53.936Z"},"updated":{"$t":"2015-07-13T13:04:49.504Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-07-13T13:04:48.019Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Fake Bidi"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cspan style\u003d\"white-space:normal\"\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"4\"\u003e\u003cb\u003eMotivation\u003c/b\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;font-size:19px;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cp\u003eFixing right-to-left [RTL] bugs in languages such as Hebrew and Arabic can be challenging if you don't speak an RTL language.\u003c/p\u003e\u003cp\u003eFake BiDi introduces the concept of a \"fake\" locale [one that doesn't correspond to a real language and isn't incorporated into the binary] which displays reversed English words in an RTL context.  This allows any developer who understands English to reason about RTL issues and UI.\u003c/p\u003e\u003cp\u003eExample: the English string \"\u003cspan\u003eHello World!\u003c/span\u003e\" becomes \"\u003cspan\u003e!dlroW olleH\u003c/span\u003e\" under Fake Bidi.\u003c/p\u003e\u003cp\u003eAnother important advantage of having a Fake BiDi locale is that it allows running tests that depend on RTL language strings without actually having those strings translated.  This means that we can use automated testing tools (such as \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:56961bee401bd960\" class\u003d\"disabled\"\u003eBiDiChecker\u003c/a\u003e) on UI where either the strings have been updated and need re-translation or there exist new strings which haven't been translated yet.\u003c/p\u003e\u003cp\u003eFor additional information about fake bidi and pseudo locales, check out \u003cspan\u003e\u003ca href\u003d\"http://code.google.com/p/chromium/issues/detail?id\u003d73052\"\u003ehttp://code.google.com/p/chromium/issues/detail?id\u003d73052\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003c/pre\u003e\u003c/span\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"4\"\u003e\u003cb\u003e\u003cu\u003eUsing Fake Bidi\u003c/u\u003e\u003c/b\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"max-width:80em;padding-left:0.7em\"\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"4\" style\u003d\"font-family:arial,sans-serif;white-space:pre-wrap\"\u003e\u003cb\u003eThe following directions are obsolete. Support for the --locale_pak flag was removed in \u003c/b\u003e\u003c/font\u003e\u003cspan style\u003d\"background-color:transparent;white-space:pre-wrap\"\u003e\u003cfont color\u003d\"#ff0000\" face\u003d\"arial, sans-serif\" size\u003d\"4\"\u003e\u003cb\u003ehttps://codereview.chromium.org/291913003/. (The fake-bidi.pak file is still being generated, however, and BidiChecker browser tests still exist.)\u003c/b\u003e\u003c/font\u003e\u003c/span\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cspan style\u003d\"font-family:monospace;font-size:medium\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eDuring the build process, \u003cu\u003ea \u003c/u\u003e\u003c/font\u003e\u003ci style\u003d\"font-family:arial,sans-serif\"\u003e\u003cu\u003efake-bidi.pak\u003c/u\u003e\u003c/i\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cu\u003e is generated next to the Chrome executable\u003c/u\u003e, in a directory called \u003ci\u003epseudo_locales\u003c/i\u003e\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e. I.e., if your build uses make, it will be in out/Debug/pseudo_locales.\u003c/font\u003e\u003c/span\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003e\u003cu\u003e\u003cstrike\u003eMac:\u003c/strike\u003e\u003c/u\u003e\u003c/b\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cu\u003e\u003cstrike\u003eTo launch Chrome with Fake Bidi, pass the following arguments:\u003c/strike\u003e\u003c/u\u003e\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cu\u003e\u003cstrike\u003e\u003cfont face\u003d\"'courier new', monospace\" size\u003d\"3\"\u003e\u003ci\u003e--locale_pak\u003d/path/to/pseudo_locales/fake-bidi.pak \u003c/i\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:medium\"\u003e\u003ci\u003e-AppleLanguages \"(he)\"\u003c/i\u003e\u003c/span\u003e\u003c/strike\u003e\u003c/u\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cu\u003e\u003cstrike\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e(Note that you may pass any (RTL) language code to \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e-AppleLanguages\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e in order to simulate any language you need.)\u003c/font\u003e\u003c/strike\u003e\u003c/u\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cu\u003e\u003cstrike\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;font-size:medium\"\u003eKnown Issue\u003c/span\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;font-size:medium\"\u003e: On launch, chrome will attempt to navigate to \"(he)\". Just close this tab and move on.\u003c/span\u003e\u003c/strike\u003e\u003c/u\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cu\u003e\u003cstrike\u003e\u003cbr /\u003e\u003c/strike\u003e\u003c/u\u003e\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cb\u003e\u003cu\u003e\u003cstrike\u003eLinux / Windows:\u003c/strike\u003e\u003c/u\u003e\u003c/b\u003e\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;white-space:normal\"\u003e\u003cpre style\u003d\"font-size:14px;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cu\u003e\u003cstrike\u003eTo launch Chrome with Fake Bidi, pass the following arguments:\u003c/strike\u003e\u003c/u\u003e\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-size:14px;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cu\u003e\u003cstrike\u003e\u003cfont face\u003d\"'courier new', monospace\" size\u003d\"3\"\u003e\u003ci\u003e--locale_pak\u003d/path/to/pseudo_locales/fake-bidi.pak \u003c/i\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:medium\"\u003e\u003ci\u003e--lang\u003dhe\u003c/i\u003e\u003c/span\u003e\u003c/strike\u003e\u003c/u\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-size:14px;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cu\u003e\u003cstrike\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e(Note that you may pass any (RTL) language code to \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e--lang\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e in order to simulate any language you need.)\u003c/font\u003e\u003c/strike\u003e\u003c/u\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-size:14px;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"4\"\u003e\u003cb\u003e\u003cu\u003eAutomated tests using Fake Bidi\u003c/u\u003e\u003c/b\u003e\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003cpre style\u003d\"font-size:14px;white-space:pre-wrap;max-width:80em;padding-left:0.7em\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eBidiChecker is currently being run both in English and in Fake Bidi from the \u003ci\u003ebrowser_tests\u003c/i\u003e executable. Check out the page about \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:56961bee401bd960\" class\u003d\"disabled\"\u003eBidiChecker\u003c/a\u003e for more info.\u003c/font\u003e\u003c/font\u003e\u003c/pre\u003e\u003c/span\u003e\u003c/font\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1447271005938918470"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/testing/fake-bidi"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8386826802801315030"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8386826802801315030"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8386826802801315030"}],"author":[{}],"sites$pageName":{"$t":"fake-bidi"},"sites$revision":{"$t":"15"}},{"gd$etag":"\"XCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6221461143622794976"},"published":{"$t":"2009-06-01T18:07:44.893Z"},"updated":{"$t":"2015-06-29T23:01:12.097Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-08-25T13:47:50.597Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chromium build infrastructure"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cimg src\u003d\"http://www.google.com/chart?chc\u003dsites\u0026amp;cht\u003dd\u0026amp;chdp\u003dsites\u0026amp;chl\u003d%5B%5BPage+listing'%3D20'f%5Cv'a%5C%3D0'10'%3D499'0'dim'%5Cbox1'b%5CF6F6F6'fC%5CF6F6F6'eC%5C0'sk'%5C%5B%22Subpage+Listing%22'%5D'a%5CV%5C%3D12'f%5C%5DV%5Cta%5C%3D10'%3D0'%3D500'%3D297'dim'%5C%3D10'%3D10'%3D500'%3D297'vdim'%5Cbox1'b%5Cva%5CF6F6F6'fC%5CC8C8C8'eC%5C'a%5C%5Do%5CLauto'f%5C\u0026amp;sig\u003dlxEPbO98PQKCTIgDHMqrwU0hJD8\" data-type\u003d\"subpages\" data-props\u003d\"align:left;borderTitle:Subpage Listing;displayAs:TOC;maxDepth:6;rootPage:THIS_PAGE;\" width\u003d\"500\" height\u003d\"300\" style\u003d\"display:block;text-align:left;margin-right:auto;\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1447271005938918470"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6221461143622794976"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6221461143622794976"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6221461143622794976"}],"author":[{"name":{"$t":"Marc-Antoine Ruel"},"email":{"$t":"maruel@chromium.org"}}],"sites$pageName":{"$t":"chromium-build-infrastructure"},"sites$revision":{"$t":"15"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/347914180521038807"},"published":{"$t":"2015-06-16T21:55:36.716Z"},"updated":{"$t":"2015-06-16T22:01:21.153Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-16T22:01:20.199Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Libraries Guide"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chromium-base-libraries\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eChromium base libraries\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Blink-s-WTF-library\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eBlink's WTF library\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Chromium-base-libraries\" /\u003eChromium base libraries\u003c/h2\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/coding-style/important-abstractions-and-data-structures\"\u003eImportant Abstractions and Data Structures\u003c/a\u003e\u003cbr /\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/smart-pointer-guidelines\"\u003eSmart Pointer Guidelines\u003c/a\u003e\u003cbr /\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/chromium-string-usage\"\u003eChromium String usage\u003c/a\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Blink-s-WTF-library\" /\u003eBlink's WTF library\u003c/h2\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://docs.google.com/document/d/1kOCUlJdh2WJMJGDf-WoEQhmnjKLaOYRbiHz5TiGJl14/edit#\" style\u003d\"font-size:10pt;background-color:transparent\"\u003eStrings in Blink\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/libraries-guide"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/347914180521038807"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/347914180521038807"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/347914180521038807"}],"author":[{"name":{"$t":"Jeffrey Yasskin"},"email":{"$t":"jyasskin@chromium.org"}}],"sites$pageName":{"$t":"libraries-guide"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"UCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5663636149949114440"},"published":{"$t":"2014-07-08T18:44:46.537Z"},"updated":{"$t":"2015-06-16T21:42:54.095Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-16T21:42:53.137Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"JavaScript Unit tests Cookbook for Chrome Remote Desktop"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-2\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOverview\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Key-features\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eKey features\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-In-a-nut-shell\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eIn a nut shell\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-do-I-...\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHow do I ...\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Create-a-new-test-case-\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eCreate a new test case?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Run-the-test-locally-\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eRun the test locally?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Organize-my-test-\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003eOrganize my test?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Use-asserts-\"\u003e\u003cstrong\u003e4.4 \u003c/strong\u003eUse asserts?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Mock-out-existing-components-\"\u003e\u003cstrong\u003e4.5 \u003c/strong\u003eMock out existing components?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-See-the-coverage-number-\"\u003e\u003cstrong\u003e4.6 \u003c/strong\u003eSee the coverage number?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Debug-a-test-failure-\"\u003e\u003cstrong\u003e4.7 \u003c/strong\u003eDebug a test failure?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Run-my-unit-test-in-the-browser-test-\"\u003e\u003cstrong\u003e4.8 \u003c/strong\u003eRun my unit test in the browser test?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Documentation-and-Design-Docs\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eDocumentation and Design Docs\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h2\u003e\r\n\u003cp\u003eThis page explains how easy it is write a JavaScript Unit test for chrome remote desktop using QUnit.\u003c/p\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\" /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests/QUnit.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1415144023215/developers/javascript-unittests/QUnit.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Key-features\" /\u003eKey features\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003eCode coverage report with blanket.js\u003c/li\u003e\r\n\u003cli\u003eSupports mocks, stubs and spies via sinon.js\u003c/li\u003e\r\n\u003cli\u003eSupports DOM testing.\u003c/li\u003e\r\n\u003cli\u003eSupports Async testing. (Promises, setTimeouts, etc)\u003c/li\u003e\r\n\u003cli\u003eCan be run as a browser test on try-bots and built-bots\u003c/li\u003e\r\n\u003cli\u003eCan be run as a standalone page to facilitate fast development\u003c/li\u003e\r\n\u003cli\u003eCan be debugged easily with the Developer console.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cdiv\u003eCurrently, the QUnit infrastructure is only used by the chrome remote desktop team.  It can be easily extended to other teams if there are interests\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-In-a-nut-shell\" /\u003eIn a nut shell\u003c/h2\u003e\r\n\u003cdiv\u003eThe key components are:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003e\u003cb\u003eQUnit \u003c/b\u003eis the overall JavaScript unit testing framework.  It provides a test store, asserts and test reporting.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eSinonJS \u003c/b\u003eprovides a mocking/spying/stubbing framework to make writing test easier.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eBlanketJS \u003c/b\u003eprovides code coverage numbers.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eQUnitBrowserTestRunner \u003c/b\u003emakes it possible to run the unit test in browser tests.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-do-I-...\" /\u003eHow do I ...\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Create-a-new-test-case-\" /\u003eCreate a new test case?\u003c/h3\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003e1. Create a new file under \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ci\u003esrc/remoting/unittests\u003c/i\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003e, the filed should be named as test_\u0026lt;module_name\u0026gt;.js, here is an example for \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ci\u003etest_math.js\u003c/i\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e// Copyright 2014 The Chromium Authors. All rights reserved.\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e// Use of this source code is governed by a BSD-style license that can be\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e// found in the LICENSE file.\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e(function() {\u003cbr /\u003e\r\n\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e'use strict';\u003cbr /\u003e\r\n\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003eQUnit.module('Math.floor', {\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  beforeEach: function() {\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e    ...\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  },\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  afterEach: function() {\u003c/code\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003ccode\u003e  }\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e});\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e\u003cbr /\u003eQUnit.test('should round down a floating point number', function(assert) {\u003c/code\u003e\u003cbr /\u003e\r\n\u003cspan\u003e\u003ccode\u003e    assert.\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003e\u003ccode\u003eequal(Math.floor(1.1), 1);\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003e});\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\r\n\u003ccode\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;line-height:13.3333320617676px\"\u003eQUnit.\u003c/span\u003etest('should work for negative numbers', function(assert) {\u003c/code\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif\"\u003e\u003ccode\u003e    assert.\u003c/code\u003e\u003c/span\u003e\u003ccode\u003eequal(Math.floor(-1.1), 2);\u003c/code\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif;font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003e});\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\r\n\u003ccode\u003e\u003cbr /\u003e\r\n})();\u003c/code\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cp\u003e2. Add the file to the \u003cb\u003e'remoting_webapp_unittest_cases'\u003c/b\u003e variable in \u003cb\u003e\u003ci\u003esrc/remoting/remoting_webapp_files.gypi\u003c/i\u003e\u003c/b\u003e\u003c/p\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003ccode\u003e# The unit test cases for the webapp\u003c/code\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003e'remoting_webapp_unittest_cases': [\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e    ...,\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003e    'webapp/unittests/test_math.js',\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003e],\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cp\u003e3. Update gyp\u003c/p\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)\" /\u003e\r\n\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"border:1px solid rgb(211,211,211);display:block;padding:0.5em 0px 0.5em 1em;line-height:1;background-color:rgb(239,239,239)\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003egclient runhooks\u003c/code\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cp\u003e4. Build the test\u003c/p\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eninja -C out/Debug -j500 remoting_webapp_unittests\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Run-the-test-locally-\" /\u003eRun the test locally?\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-For-the-chrome-remote-desktop-unit-test\" /\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eFor the chrome remote desktop unit test\u003c/span\u003e\u003c/h4\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eGo to the source directory\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e./remoting/tools/run_webapp_unittests.py\u003c/code\u003e\u003c/div\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\nWhat the script does under the hood is to run the test page in \u003cb\u003e\u003ci\u003eChrome\u003c/i\u003e\u003c/b\u003e with the --\u003cb\u003e\u003ci\u003eallow-file-access flag\u003c/i\u003e\u003c/b\u003e.  \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ci\u003e\u003cb\u003eBlanketjs\u003c/b\u003e\u003c/i\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e need to load the source file locally to instrument it for code coverage.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eIf you make changes to your test code, you don't need to rebuild after this.  Simply edit your test code and hit F5\u003c/span\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Organize-my-test-\" /\u003eOrganize my test?\u003c/h3\u003e\r\n\u003cp style\u003d\"font-size:13px;font-weight:normal;margin:0px 0px 0px 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eThere should be one test file per product file, e.g.\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u0026lt;product_file_name\u0026gt;_unittest.js\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\u003cp\u003eGroup each class into its own module, e.g.\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003ccode\u003eQUnit.module('class_name')\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003e\u003ccode\u003e\u003cspan style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif\"\u003eCreate one test case per behavior.  The name of a test should be an English statement in the format of method1() should ... '\u003cbr /\u003eIf a method has multiple behavior, you can create multiple test for it.\u003c/span\u003e\u003c/code\u003e\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\r\n\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003cp\u003e\u003ccode\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;line-height:13.3333320617676px\"\u003eQUnit.\u003c/span\u003emodule('class_name');\u003c/code\u003e\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\u003cp\u003e\u003ccode\u003e\r\ntest('method1() should have behavior X', function (assert) {\u003c/code\u003e\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\u003cp\u003e\u003ccode\u003e    // test body\u003c/code\u003e\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\u003cp\u003e\u003ccode\u003e});\u003c/code\u003e\u003c/p\u003e\u003cdiv\u003e\u003cp\u003e\u003ccode\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;line-height:13.3333320617676px\"\u003eQUnit.\u003c/span\u003etest('method1() should have behavior Y', function (\u003c/code\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13.3333330154419px;line-height:13.3333320617676px\"\u003eassert\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);line-height:1;font-size:10pt\"\u003e) {\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp\u003e\u003ccode\u003e    // test body\u003c/code\u003e\u003c/p\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif\" /\u003e\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:13.333332061767578px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cp\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e});\u003c/code\u003e\u003c/p\u003e\u003c/div\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cp\u003e\u003ccode\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;line-height:13.3333320617676px\"\u003eQUnit.\u003c/span\u003etest('method2() should have behavior Z', function (\u003c/code\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13.3333330154419px;line-height:13.3333320617676px\"\u003eassert\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);line-height:1;font-size:10pt\"\u003e) {\u003c/span\u003e\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\u003cp\u003e\u003ccode\u003e    // test body\u003c/code\u003e\u003c/p\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\r\n\u003cp\u003e\u003ccode\u003e});\u003c/code\u003e\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Use-asserts-\" /\u003eUse asserts?\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eQUnit is assertion-based.  An assert is claim about the behavior of the piece of code under test.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eThe most common asserts are:\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003ccode\u003eok(condition)\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003ccode\u003eequal(expected, actual)\u003c/code\u003e\u003c/div\u003e\r\n\u003c/font\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eSee \u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"font-weight:normal;font-size:small;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"http://api.qunitjs.com/category/assert/\" rel\u003d\"nofollow\"\u003ehttp://api.qunitjs.com/category/assert/\u003c/a\u003e for the API refere\u003c/font\u003ence.\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Mock-out-existing-components-\" /\u003eMock out existing components?\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003eSinonJS allows you to mock existing components. SinonJS provides three key functionalities\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cb\u003eSpying\u003c/b\u003e - \u003cb\u003eTrack calls to functions\u003c/b\u003e\u003cbr /\u003e\r\n\u003cb\u003e Stubs\u003c/b\u003e - Create functions with\u003cb\u003e pre-programmed behaviors\u003c/b\u003e. When wrapped around existing function with a stub, the original function is not called.\u003cbr /\u003e\r\n\u003cb\u003e Mocking\u003c/b\u003e - Create functions with \u003cb\u003epre-programmed behaviors\u003c/b\u003e and \u003cb\u003epre-programmed expectations\u003c/b\u003e\u003cbr /\u003e\r\n \u003cbr /\u003e\r\nSee \u003ca href\u003d\"http://sinonjs.org/docs/\" rel\u003d\"nofollow\"\u003ehttp://sinonjs.org/docs/\u003c/a\u003e for the API reference.\u003c/blockquote\u003e\r\n \r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-See-the-coverage-number-\" /\u003eSee the coverage number?\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eClick on \u003c/span\u003e\u003cb style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ci\u003eEnable Coverage\u003c/i\u003e\u003c/b\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e in the test page\u003cbr /\u003e\r\n\u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests/EnableCoverage.png?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1415144023215/developers/javascript-unittests/EnableCoverage.png\" /\u003e\u003c/a\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe number will be reported inline, with \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003euncovered lines displayed with a \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:rgb(230,195,199)\"\u003ered highlighted background.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests/Coverage.png?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1415144023215/developers/javascript-unittests/Coverage.png\" /\u003e\u003c/a\u003e\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Debug-a-test-failure-\" /\u003eDebug a test failure?\u003cbr /\u003e\r\n\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal;background-color:transparent\"\u003eSince the QUnit test runs in the browser, you can debug a test failure just like any web page using the developer console.\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Run-my-unit-test-in-the-browser-test-\" /\u003eRun my unit test in the browser test?\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eYou can also run the test under the browser test infrastructure\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e./out/Debug/browser_tests --gtest_filter\u003dQUnitBrowserTestRunner.Remoting_Webapp_Js_Unittest\u003c/code\u003e\u003c/div\u003e\r\n\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003cbr /\u003eIf the test fails, it will print out the test case that fails:\u003cbr /\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003eValue of: passed\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e\u003cfont size\u003d\"2\"\u003e  \u003c/font\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003eActual: false\u003c/font\u003e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003eExpected: true\u003cbr /\u003e\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e1 test failed:\u003cbr /\u003e\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e  base.EventSource.removeEventListener.should work even if the listener is removed during |raiseEvent|\u003cbr /\u003e\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e    1. expected spy to be called twice but was called once\u003cbr /\u003e\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e    spy(undefined)\u003cbr /\u003e\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e        at Object.sinon.assert.fail (file:///usr/local/google/home/kelvinp/enlistments/chromium/src/out/Release/remoting/unittests/sinonjs/sinon-qunit.js:36:11)\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e[  FAILED  ] QUnitBrowserTestRunner.Remoting_Webapp_Js_Unittest, where TypeParam \u003d  and GetParam() \u003d  (1340 ms)\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003cbr /\u003eThe easiest way to debug the failure is to run the failed module manually in chrome and debug from there.\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\r\n\u003c/blockquote\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Documentation-and-Design-Docs\" /\u003eDocumentation and Design Docs\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-color:rgb(136,136,136);border-width:1px\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:155px;height:25px\"\u003eDesign docs\u003c/td\u003e\r\n\u003ctd style\u003d\"width:798px;height:25px\"\u003e \u003ca href\u003d\"https://docs.google.com/a/chromium.org/document/d/1SOacnv91zFWEqtietEG6ubh3qDfpds3J3e1Bb1Lfgys/edit?usp\u003dsharing\"\u003ehttps://docs.google.com/a/chromium.org/document/d/1SOacnv91zFWEqtietEG6ubh3qDfpds3J3e1Bb1Lfgys/edit?usp\u003dsharing\u003c/a\u003e\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:155px;height:14px\"\u003eQUnit documentation \u003c/td\u003e\r\n\u003ctd style\u003d\"width:798px;height:14px\"\u003e \u003ca href\u003d\"http://api.qunitjs.com/\" rel\u003d\"nofollow\"\u003ehttp://api.qunitjs.com/\u003c/a\u003e\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:155px;height:28px\"\u003eBlanketJS documentation\u003c/td\u003e\r\n\u003ctd style\u003d\"width:798px;height:28px\"\u003e \u003ca href\u003d\"http://blanketjs.org/\" rel\u003d\"nofollow\"\u003ehttp://blanketjs.org/\u003c/a\u003e\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:155px;height:28px\"\u003eSinonJS documentation\u003c/td\u003e\r\n\u003ctd style\u003d\"width:798px;height:28px\"\u003e \u003ca href\u003d\"http://sinonjs.org/docs/\" rel\u003d\"nofollow\"\u003ehttp://sinonjs.org/docs/\u003c/a\u003e\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5663636149949114440"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4061537406890692522/4"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663636149949114440"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663636149949114440"}],"author":[{"name":{"$t":"Kelvin Poon"},"email":{"$t":"kelvinp@chromium.org"}}],"sites$pageName":{"$t":"javascript-unittests"},"sites$revision":{"$t":"19"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5754810029430160012"},"published":{"$t":"2008-10-14T00:44:52.187Z"},"updated":{"$t":"2015-06-15T18:05:22.197Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-15T18:05:20.834Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Form Autofill"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"font-style:normal\"\u003e\u003cb\u003e\u003cfont size\u003d\"4\"\u003eObjective\u003cbr /\u003e\u003c/font\u003e\u003c/b\u003e\u003c/span\u003e\u003cbr /\u003eA feature in Chrome to automatically fill out an html form with appropriate data.\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Background\" /\u003e\u003cfont size\u003d\"4\"\u003e\r\n Background\u003c/font\u003e\u003c/h2\u003eMost browsers have an autofill feature, and Google toolbar for Firefox\r\nhas an autofill feature. Every browser presents a slightly different\r\nuser experience, but the basic paradigms of how it should appear to the\r\nuser are well established.\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003e\u003cfont size\u003d\"4\"\u003eOther Implementations\u003c/font\u003e\u003c/b\u003e\u003cbr /\u003e\u003cul\u003e\u003cli\u003e\r\n \u003ca href\u003d\"http://toolbar.google.com/T5/intl/en/features.html#autofill\"\u003eGoogle Toolbar\u003c/a\u003e\r\n \u003c/li\u003e\u003cli\u003e\r\n \u003ca href\u003d\"http://support.mozilla.com/en-US/kb/Form+autocomplete\" rel\u003d\"nofollow\"\u003eFirefox\u003c/a\u003e\r\n \u003c/li\u003e\u003cli\u003e\r\n \u003ca href\u003d\"http://docs.info.apple.com/article.html?path\u003dSafari/2.0/en/ibr47.html\" rel\u003d\"nofollow\"\u003eSafari\u003c/a\u003e\r\n \u003c/li\u003e\u003cli\u003e\r\n \u003ca href\u003d\"http://msdn.microsoft.com/en-us/library/ms533032%28VS.85%29.aspx\" rel\u003d\"nofollow\"\u003eInternet Explorer\u003c/a\u003e\r\n \u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003e\u003cfont size\u003d\"4\"\u003e\r\n Overview\u003c/font\u003e\u003c/h2\u003eEvery time the user submits a form, entries in text input fields\r\norganized by the name of the field specified in html get stored in the SQLite database under the profile.\u003cbr /\u003e\u003cbr /\u003e\r\nWhen the user opens a webpage containing a form and types into one of\r\nthe fields, Chrome checks the database for past entries into fields\r\nwith the same name.  As the user types, a pop-up menu appears\r\nallowing the user to select from entries which match the prefix already\r\nentered.\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-User-Experience\" /\u003e\u003cfont size\u003d\"4\"\u003e\r\n User Experience\u003c/font\u003e\u003c/h2\u003eThe user visits a website containing a form and commences to filling it\r\nout. When the user starts filling out a field autofill kicks in and\r\ndisplays a menu showing frequently entered data into fields\r\nwith the same name as the currently focused field.\u003cbr /\u003e\u003cb\u003e\u003cfont size\u003d\"4\"\u003e\u003cbr /\u003eImplementation\u003c/font\u003e\u003c/b\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003eData Structures\u003cbr /\u003e\u003cbr /\u003e\u003c/b\u003eAutofillForm: A struct for storing name/value pairs as well as origin and action urls.  One of these gets constructed when the user submits the form.  The class uses a static factory method AutofillForm::CreateAutofillForm() which might return NULL if the form itself is unsuitable for autofilling.\u003cbr /\u003e\u003cbr /\u003eAutofillManager: The per-tab autofill manager.  Handles receiving form data from the renderer and\r\nstoring and retrieving name/value pairs through WebDataService.  Each WebContents has a single AutofillManager which gets accessed by the method GetAutofillManager().\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003eProgram Flow\u003c/b\u003e\u003cbr /\u003e\u003cbr /\u003eWhen the user submits a form, the form gets sent to\r\nAutofillForm::CreateAutofillForm().  If the form is suitable\r\nfor autofill, the return value will be a new AutofillForm holding all\r\nthe values that the user entered in the form. \r\nWebFrameLoaderClient::dispatchWillSubmitForm() passes the AutofillForm\r\nas\r\nthe argument of its delegate's function OnAutofillFormSubmitted().  The\r\ndelegate, provided it is a RenderView, sends a\r\nViewHostMsg_AutofillFormSubmitted message to its RenderViewHost.  Upon\r\ngetting the message, the RenderViewHost then forwards the form to its\r\ndelegate as the argument of AutofillFormsSeen().  That delegate should\r\nbe a WebContents.  The WebContents contains a pointer to its\r\nAutofillManager, and passes the form to\r\nAutofillManager::StoreFormEntriesInWebDatabase().  The AutofillManager\r\nthen uses WebDataService to record the submitted form entries into the\r\nlocal database.\u003cbr /\u003e\u003cbr /\u003eWhen the user navigates to a form that is potentially fillable by\r\nautofill, WebFrameLoaderClient::dispatchDidFinishDocumentLoad() calls WebFrameLoaderClient::RegisterAutofillListeners() which attaches a webkit_glue::FormAutocompleteListener to each text input field.  The FormAutocompleteListener waits for keyboard events in the field and calls RenderView::QueryFormFieldAutofill for suggestions.  The RenderView sends a message to its RenderViewHost which calls GetAutofillSuggestions on its delegate.  That delegate should be a WebContents.  WebContents::GetAutofillSuggestions() gets the list of suggestions from its AutofillManager.  The AutofillManager gets the suggestion list from WebDataService, and then calls back RenderViewHost::AutofillSuggestionsReturned().\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003eTables in the SQLite Databse\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/b\u003eautofill: Stores in each row the following information for an entry\r\ninto a form: pair_id, name, value, count.  pair_id is an integer unique\r\nto that row in the table.  pair_id is meant to be thought of as\r\nuniquely identifying a name/value pair that has been entered. \r\nname/value pairs are only entered into one row of the autofill table. \r\nAfter that if the same value is entered in a field with that name, the\r\ncount entry in the row gets incremented, and a separate row gets\r\nentered in autofill_dates.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nautofill_dates: Gets a row added for each form element (of text input\r\ntype), every time the user submits a form.  Each row contains a pair_id\r\nidenitifying the corresponding row in the autofill table and a time\r\ndate_created indicating when that form element was added.\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Internationalization\" /\u003e\u003cfont size\u003d\"4\"\u003eInternationalization\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:large\"\u003e\u003cspan style\u003d\"font-size:13px\"\u003eInternationalization of the Autofill feature is described \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/form-autofill/internationalization-of-autofill\"\u003ehere\u003c/a\u003e.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Future-Work\" /\u003e\u003cfont size\u003d\"4\"\u003eFuture Work\u003c/font\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Fill-not-just-the-currently-focused-form-field-but-other-fields-in-the-form-once-the-user-has-identified-themselves.\" /\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003eFill not just the currently focused form field but other fields in the form once the user has identified themselves.\u003c/span\u003e\u003c/h2\u003e\u003cbr /\u003eIntroduce a profile data structure that stores specific information by\r\nuser such as names (first/last) addresses telephone numbers, and record the type of data that gets entered into a form\r\nrather than the data itself.\u003cbr /\u003e\u003cbr /\u003eHandle names in a way that accounts for fields which ask for full name on one line versus first and last name separately.\u003cbr /\u003e\u003cbr /\u003eHandle phone number entry with \"split\" fields.  Different sites require\r\nphone numbers to be entered in various formats.  Some require the\r\npunctuation, some require country code, area code, prefix and extension\r\nin separate fields.  Phone numbers are formatted differently from\r\ncountry to country.  We should add heuristics to handle these various\r\ncases.\u003cbr /\u003e\u003cbr /\u003e\r\n Allow the user to specify multiple addresses (mailing, shipping).\u003cbr /\u003e\u003cbr /\u003eJust in case autofill fills in everything wrong (such as the user is\r\nborrowing somebody's computer, and it filled in the computer's owner's\r\ninformation somehow) a gentle, unassuming control appears allowing the\r\nuser to turn autofill off for the current form.\u003cbr /\u003e\u003cbr /\u003e\r\n Allow multiple profiles.\u003cbr /\u003e\u003cbr /\u003e\r\n Allow credit card information in a profile with extra password protection.\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Privacy-and-Security-Concerns\" /\u003e\u003cfont size\u003d\"4\"\u003e\r\n Privacy and Security Concerns\u003c/font\u003e\u003c/h2\u003eAutofill should not enter information into a text field which a program\r\ncould potentially read unless the user has implicitly given consent to\r\nupload that information such as by selecting an item from a drop-down menu or hitting the submit button.  Otherwise, a\r\nsinister person could construct a website with hidden form fields which\r\nharvest personal data by getting autofilled.\u003cbr /\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"4\"\u003eSubsystem design docs\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003ca href\u003d\"https://goo.gl/LS2y6M\" style\u003d\"font-size:10pt;background-color:transparent\"\u003eSyncing autofill Wallet metadata\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/form-autofill"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5754810029430160012"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5754810029430160012"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5754810029430160012"}],"author":[{}],"sites$pageName":{"$t":"form-autofill"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1200399285482875661"},"published":{"$t":"2015-06-12T19:09:32.022Z"},"updated":{"$t":"2015-06-12T19:09:32.188Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T19:09:32.022Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"dump.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1200399285482875661"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7348747059329133392"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/memory/dump.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1200399285482875661"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1200399285482875661"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1200399285482875661"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1200399285482875661"}],"author":[{"name":{"$t":"Primiano Tucci"},"email":{"$t":"primiano@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7237298016419003667"},"published":{"$t":"2015-06-12T18:43:15.452Z"},"updated":{"$t":"2015-06-12T18:43:15.489Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T18:43:15.452Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-06-12 at 7.42.47 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7237298016419003667"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7348747059329133392"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/memory/Screen%20Shot%202015-06-12%20at%207.42.47%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7237298016419003667"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7237298016419003667"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7237298016419003667"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7237298016419003667"}],"author":[{"name":{"$t":"Primiano Tucci"},"email":{"$t":"primiano@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Xyl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8119957236299717361"},"published":{"$t":"2011-07-08T20:53:16.569Z"},"updated":{"$t":"2015-06-12T18:21:36.770Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T18:21:35.141Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Firmware Update"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-WARNING:-Remember-to-backup-your-original-firmware-The-flash-memory-contains-some-device-information-that-cannot-be-recovered-if-overwritten.\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eWARNING: Remember to backup your original firmware! The flash memory contains some device information that cannot be recovered if overwritten.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Glossary\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eGlossary\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-cros_bundle_firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ecros_bundle_firmware\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Summary\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eSummary\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Usage\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eUsage\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Options\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eOptions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-cros_write_firmware\"\u003e\u003cstrong\u003e4 \u003c/strong\u003ecros_write_firmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Updating-your-U-Boot-to-2011.12-on-Daisy\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eUpdating your U-Boot to 2011.12 on Daisy\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-x86-Development-Flow\"\u003e\u003cstrong\u003e6 \u003c/strong\u003ex86 Development Flow\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-WARNING:-Remember-to-backup-your-original-firmware-The-flash-memory-contains-some-device-information-that-cannot-be-recovered-if-overwritten.\" /\u003e\r\n\u003cdiv style\u003d\"font-weight:normal\"\u003e\r\n\u003cp\u003e\u003cfont size\u003d\"3\"\u003e\u003cfont color\u003d\"#990000\"\u003eWARNING: Remember to backup your original firmware! The flash memory contains some \u003c/font\u003e\u003cspan style\u003d\"color:rgb(153,0,0)\"\u003edevice information\u003c/span\u003e\u003cfont color\u003d\"#990000\"\u003e that cannot be recovered if overwritten.\u003c/font\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/h2\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Glossary\" /\u003eGlossary\u003c/h2\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003eBCT (Binary Chip Timings)\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003eBCT\u003c/b\u003e contains timing parameters for the\u003cb\u003e \u003c/b\u003eSOC and it used to set up its memory and basic peripherals, to allow it to read the boot loader. The BCT is packaged together with U-Boot for reading by the SOC on boot.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eBoot ROM\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eAn SOC's \u003cb\u003eBoot ROM\u003c/b\u003e is responsible for setting up the SOC to a very basic level (using the\u003cb\u003e \u003c/b\u003eBCT), setting up SDRAM and figuring out where the boot loader is. This is typically capable of loading the boot loader from USB, SPI flash, UART, eMMC / SD card and NAND flash. The Boot ROM is part of the SOC and cannot be changed other than by making a new chip. Some Boot ROMs include security features which require that boot code be signed by a special tool. Typically, Boot ROM consists of 16-32 KB of code.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eDevice tree\u003c/b\u003e \u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003esee \u003cb\u003eFDT\u003c/b\u003e.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eDTB file (Device Tree Binary)\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eA file containing a binary representation of a device tree created by the \u003ci\u003edevice tree compiler\u003c/i\u003e from the source \u003ci\u003eDTS file\u003c/i\u003e.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eDTS file \u003c/b\u003e\u003cb\u003e(Device Tree Source)\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eA file containing a source representation of the device tee. This file is compiled into binary form for use by U-Boot and kernel.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eFDT (Flattened Device Tree)\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eA \u003ci\u003eflattened device tree\u003c/i\u003e describes the hardware that is seen by U-Boot and the kernel. The device tree consists of a number of nodes containing properties like memory addresses, interrupts, size, width / height (for LCD), etc. Each node also contains a \u003ccode\u003ecompatible\u003c/code\u003e property which indicates which device driver should be used to implement the features provided by that node. We also use the FDT to pass provide configuration and verified boot information from U-Boot to the kernel. There is a different FDT for each board type, and even for each SKU (since a particular manufacturing run may change the chips that are used in some cases).\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eGBB (Google Binary Block)\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThis read-only area contains screen images for recovery mode and keys for both normal and recovery mode.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eSOC (System on Chip)\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eA name for the integrated chips common in the ARM world. They include most peripherals on chip including SDRAM,control, SPI buses, NAND, USB and LCD. Roughly speaking a basic system can be created with an SOC, some SDRAM, some Flash and a power controller\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eU-Boot\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThe boot loader is responsible for setting up all required peripherals (such as LCD, SPI flash, UARTs, eMMC) and then loading and starting the kernel. On Chrome OS this includes security requirements, so we split U-Boot into two parts: a read only image that we ship with, and a read write image which can override this when we need to update the boot loader in the field. U-Boot is linked with the VBoot library which provides its security features. U-Boot is also responsible for taking the kernel's FDT, updating it with security and boot parameters, and presenting it to the kernel. There is a single U-Boot image for all boards for a single SOC type. For example, for Tegra2 we have one U-Boot image. All run-time configuration of U-Boot is done through the FDT.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cb\u003eVBoot\u003c/b\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThe verified boot library includes routines for accessing and checking keys and signatures. A detailed description of how this works \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures\"\u003eis provided here\u003c/a\u003e.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-cros_bundle_firmware\" /\u003e\u003ccode\u003ecros_bundle_firmware\u003c/code\u003e\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h3\u003e\r\nThis is a tool for creating a firmware image and writing it to your board. It can handle the following tasks:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003ePackage together U-Boot (the boot loader) and a FDT to produce a boot image\u003c/li\u003e\r\n\u003cli\u003ePackage together the boot image, a BCT and appropriate signature to product a signed image\u003c/li\u003e\r\n\u003cli\u003eCreate a GBB with appropriate keys and images\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eCreate a full firmware image containing all the sections required for boot\u003c/li\u003e\r\n\u003cli\u003eWrite this image to a board through the USB A-A cable\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Usage\" /\u003eUsage\u003c/h3\u003e\r\n\u003cp\u003eTo create an image for a particular board, use:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003ecros_bundle_firmware -b \u0026lt;board\u0026gt; -o \u0026lt;filename\u0026gt;\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cp\u003eThis will generate an image \u003ccode\u003e\u0026lt;filename\u0026gt;\u003c/code\u003e for the board. The tool finds files it needs in \u003ccode\u003e/build/\u0026lt;board\u0026gt;/firmware\u003c/code\u003e, things like \u003ccode\u003eu-boot.bin\u003c/code\u003e, the device tree source files (in dts subdir) and so on. There are options to specify each of these manually if you want to, and this is what the ebuild does. However, it does make for a very long command line. If you are unsure what files it is picking up, use -v3.\u003c/p\u003e\r\n\u003cp\u003eBy default \u003ccode\u003ecros_bundle_firmware\u003c/code\u003e is quiet. Unless there are warnings/errors, all you will see is progress, and a command prompt when done. Use -v2, -v3 or even -v4 to change that.\u003c/p\u003e\r\n\u003cp\u003eThings you can do with this tool, which involve adding options:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eSpecify your own U-Boot image: \u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e-u u-boot.bin\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eSpecify the U-Boot used for flashing (if your U-Boot doesn't support it)\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e-U /build/\u0026lt;board\u0026gt;/firmware/u-boot.bin\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eSpecify your own FDT source file: \u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cul style\u003d\"text-align:left\"\u003e\u003cli\u003e\u003ccode\u003e-d my-board.dts\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003eNote you will need to add a -I \u0026lt;dir\u0026gt; option for each include directory needed by your fdt. For example, \u003ccode\u003e-I arch/arm/dts -I board/samsung/dts\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003eThe FDT file is automatically compiled\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eWrite the firmware to an SD card:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e-w sd:.\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003eThe \u003ccode\u003e.\u003c/code\u003e means to write to the only SD card connected to your machine. You can explicitly name the card if you like. Try \u003ccode\u003e-w sd\u003c/code\u003e to get a list of options.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eWrite the firmware over USB to the board\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e-w usb\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003eNote this works for Tegra, but currently (Apr-12) gives checksum errors for Exynos\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eGenerate a minimal image just for testing with none of the GBB and other Chrome OS stuff\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e-s\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eSave all the temporary files so you can see what happened:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e-O \u0026lt;dir\u0026gt;\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cp\u003eA full list of options is below, or use the --help flag.\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Options\" /\u003eOptions\u003c/h3\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eUsage: cros_bundle_firmware [options]\u003c/code\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003ccode\u003eOptions:\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -h, --help            show this help message and exit\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --add-config-str\u003dADD_CONFIG_STR\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Add a /config string to the U-Boot fdt\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --add-config-int\u003dADD_CONFIG_INT\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Add a /config integer to the U-Boot fdt\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -b BOARD, --board\u003dBOARD\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Board name to use (e.g. tegra2_kaen)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --bootcmd\u003dBOOTCMD     Set U-Boot boot command\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --bootsecure          Boot command is simple (no arguments) and not\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        interruptible\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -c BCT, --bct\u003dBCT     Path to BCT source file: only one can be given\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -d FDT, --dt\u003dFDT      Path to fdt binary blob .dtb file to use\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --bl1\u003dEXYNOS_BL1      Exynos preboot (BL1) file\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --bl2\u003dEXYNOS_BL2      Exynos Secondary Program Loader (SPL / BL2) file\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  --hwid\u003dHARDWARE_ID    Hardware ID string to use\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -B BMPBLK, --bmpblk\u003dBMPBLK\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Bitmap block to use\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -F FLASH_DEST, --flash\u003dFLASH_DEST\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Create a flasher to flash the device (spi, mmc)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -k KEY, --key\u003dKEY     Path to signing key directory (default to dev key)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -I INCLUDEDIRS, --includedir\u003dINCLUDEDIRS\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Include directory to search for files\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -m, --map             Output a flash map summary\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -o OUTPUT, --output\u003dOUTPUT\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Filename of final output image\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -O OUTDIR, --outdir\u003dOUTDIR\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Path to directory to use for intermediate and output\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        files\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -p, --preserve        Preserve temporary output directory\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -P POSTLOAD, --postload\u003dPOSTLOAD\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Path to post-load portion of U-Boot (u-boot-post.bin)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -s, --small           Create/write only the signed U-Boot binary (not the\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        full image)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -S SEABIOS, --seabios\u003dSEABIOS\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Legacy BIOS (SeaBIOS)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -u UBOOT, --uboot\u003dUBOOT\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Executable bootloader file (U-Boot)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -U UBOOT_FLASHER, --uboot-flasher\u003dUBOOT_FLASHER\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Executable bootloader file (U-Boot) to use for\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        flashing (defaults to the same as --uboot)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -C COREBOOT, --coreboot\u003dCOREBOOT\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Executable lowlevel init file (coreboot)\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -v VERBOSITY, --verbosity\u003dVERBOSITY\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Control verbosity: 0\u003dsilent, 1\u003dprogress, 3\u003dfull,\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        4\u003ddebug\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e  -w WRITE, --write\u003dWRITE\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e                        Write firmware to device (usb, sd)\u003c/code\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-cros_write_firmware\" /\u003e\u003ccode\u003ecros_write_firmware\u003c/code\u003e\u003c/h2\u003e\r\n\u003cp\u003eIf you already have an image, you can use this tool to write it to an SD card or over USB. However, you might find '\u003ccode\u003ecros_bundle_firmware -w\u003c/code\u003e' more flexible.\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003ecros_write_firmware\u003c/code\u003e\u003ccode\u003e -b daisy -\u003c/code\u003e\u003ccode\u003ei \u0026lt;image\u0026gt; -w sd:.\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Updating-your-U-Boot-to-2011.12-on-Daisy\" /\u003eUpdating your U-Boot to 2011.12 on Daisy\u003cbr /\u003e\r\n\u003c/h2\u003e\r\n\u003cp\u003eYou can do this without USB download using an SD card if you like. Please follow these steps:\u003c/p\u003e\r\n\u003col\u003e\u003cli\u003eGet an SD card and put it into your card reader. The contents of this will be overwritten.\u003c/li\u003e\r\n\u003cli\u003eGet the latest source:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ repo sync\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eBuild everything\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ build_packages --board daisy\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ emerge-daisy chromeos-u-boot\u003cbr /\u003e\r\n\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ emerge-daisy sys-boot/chromeos-bootimage\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eWrite the firmware to your SD card (-F means to create an automatic flasher)\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ \u003c/code\u003e\u003cspan\u003e\u003ccode\u003ecros_bundle_firmware --add-config-int load_env 1 -b daisy -w sd:. -F spi\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n# Add '-d exynos5250-snow' for snow\u003cbr /\u003e\r\n\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eInsert the SD card into your daisy board\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eHold down the button which is labelled T20_REC / FW_DEBUG / DFU_REC depending on whether you are using \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eServo 2\u003c/a\u003e, Daisy or Min-Servo.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003ePress COLD_RST_L / KBC_RST / C_RST, then PWR_BUTTON to switch on, to boot from the SD card.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eWhen it starts up, you should see a console on your servo UART, and it will start flashing your board.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eWhen finished, type 'reset' into the terminal, or \u003cspan\u003epress COLD_RST_L / KBC_RST / C_RST again, then PWR_BUTTON to switch on.\u003c/span\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nSteps 8  can also be done via servod:\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003edut-control fw_up:on fw_up cold_reset:on cold_reset cold_reset:off cold_reset \\\u003c/code\u003e\r\n\u003cdiv\u003e\u003ccode\u003e            pwr_button:press pwr_button sleep:2 pwr_button:release pwr_button \\\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e            cold_reset:off cold_reset fw_up:off fw_up cpu_uart_en:on \u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-x86-Development-Flow\" /\u003ex86 Development Flow\u003c/h2\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cb style\u003d\"font-size:medium\"\u003eBuilding from the firmware branch\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cb style\u003d\"font-size:medium\"\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe ToT is not guaranteed to build usable firmware for older boards, so it is often necessary to retrieve an old branch to do so.  These steps were used to build the Link firmware from source:\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003erepo init -u \u003ci\u003e\u0026lt;internal-manifest-url\u0026gt;\u003c/i\u003e \\\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e    --repo-url\u003d'https://chromium.googlesource.com/external/repo.git'\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e    -b firmware-link-2695.B \u003c/code\u003e\u003cbr /\u003e\u003ccode\u003erepo sync\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003ecros_workon-link start chromeos-base/chromeos-ec \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    sys-boot/chromeos-u-boot \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    chromeos-base/vboot_reference \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    chromeos-base/vboot_reference-firmware \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    sys-boot/chromeos-coreboot-link \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    sys-boot/chromeos-seabios \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    chromeos-base/chromeos-firmware-link\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003eemerge-link chromeos-ec \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    vboot_reference-firmware \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    chromeos-u-boot \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    chromeos-coreboot-link \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    chromeos-bootimage\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003eThis should create \u003ccode\u003eimage-link.bin\u003c/code\u003e in \u003ccode\u003e/build/link/firmware\u003c/code\u003e under the chroot.\u003cbr /\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cb style\u003d\"font-size:medium\"\u003eUsing flashrom\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont size\u003d\"2\" style\u003d\"color:rgb(0,0,0);font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cfont face\u003d\"arial\"\u003eThe \u003c/font\u003e\u003c/font\u003e\u003ccode\u003eflashrom\u003c/code\u003e\u003cfont size\u003d\"2\" style\u003d\"color:rgb(0,0,0);font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cfont face\u003d\"arial\"\u003e command can be run from a root shell on the device, or it can be used from a development PC connected via servo.  See \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/cros-flashrom\"\u003ehere\u003c/a\u003e for more detailed instructions on usage.\u003c/font\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cb style\u003d\"font-size:medium;font-family:arial;text-align:-webkit-auto;background-color:transparent\"\u003eUsing the SPI flash emulator\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003eThe instructions in this section assume that you have a \u003ca href\u003d\"http://www.dediprog.com/pd/spi-flash-solution/em100pro\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eDediprog EM100\u003c/a\u003e hooked up to the system.  This hardware allows for downloading a new firmware image to the board in mere seconds, rather than waiting a few minutes to reflash a physical SPI memory device.\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003eTo build a new firmware image, write it to your em100 and reset your link (using servo2):\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\" /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003ccode\u003e$ USE\u003ddev emerge-link chromeos-u-boot\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003ccode\u003e$ cros_bundle_firmware -b link --bootcmd vboot_twostop -w em100\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e(the 'dev' flag reduces the 870KB of spew from the U-Boot ebuild, printing only warnings and errors)\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003eIf you want a U-Boot serial console, but don't want to coreboot to print out all its serial info, you can build a coreboot WITHOUT the \u003ccode\u003eUSE\u003dpcserial\u003c/code\u003e flag, and then:\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ cros_bundle_firmware -b link --add-node-enable console 1 --bootcmd vboot_twostop -w em100\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:arial;font-size:small;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px\"\u003eThis enables the console node in the device tree, thus turning on the serial console in U-Boot.\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/593897542665142458"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/firmware-update"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8119957236299717361"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8119957236299717361"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8119957236299717361"}],"author":[{"name":{"$t":"Simon Glass"},"email":{"$t":"sjg@chromium.org"}}],"sites$pageName":{"$t":"firmware-update"},"sites$revision":{"$t":"26"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2828410418037192164"},"published":{"$t":"2015-06-12T18:06:10.122Z"},"updated":{"$t":"2015-06-12T18:08:01.090Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T18:08:01.067Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"2. MemoryInfra- From trace JSON to Tracks.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2828410418037192164"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7348747059329133392"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/memory/2.%20MemoryInfra-%20From%20trace%20JSON%20to%20Tracks.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2828410418037192164"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2828410418037192164"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2828410418037192164"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2828410418037192164"}],"author":[{"name":{"$t":"Primiano Tucci"},"email":{"$t":"primiano@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"WSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5581542598653454687"},"published":{"$t":"2014-02-23T19:31:19.604Z"},"updated":{"$t":"2015-06-12T16:55:04.102Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T16:55:02.980Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Toshiba CB30 Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Running-Chromium-OS\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eRunning Chromium OS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disclaimer\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eDisclaimer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-Inside-\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eWhat's Inside?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"http://www.google.com/intl/en/chrome/devices/chromebooks.html#toshiba\"\u003eToshiba CB30 Chromebook\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003eCPU: Haswell Celeron 2995U. 1.4GHz, dual-core, 2MB Cache\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GB or 4GB DDR3 (Not upgradeable)\u003c/li\u003e\r\n\u003cli\u003eDisplay: \u003cspan style\u003d\"background-color:transparent\"\u003e13.3\" 1366x768\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eDisk: 16GB SSD (Not upgradeable)\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eI/O:\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI port\u003c/li\u003e\r\n\u003cli\u003e2 x USB 3\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\r\n\u003cli\u003eCamera \u0026amp; mic\u003c/li\u003e\r\n\u003cli\u003eKeyboard \u0026amp; touchpad\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eUSB ports can handle some Ethernet dongles\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eServo header\u003c/a\u003e: \u003c/span\u003eStandard 2x25 / AXK750347G\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eDetails for working with developer mode can be found \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook\"\u003eon this page\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Running-Chromium-OS\" /\u003eRunning Chromium OS\u003c/h2\u003e\r\n\r\n\u003cp\u003eBefore you start fiddling with your own builds it is strongly recommend to create a recovery USB stick or SD card. As long as you don't disable hardware write protect on the system \u0026amp; EC firmware, you can get your machine back into working order by entering Recovery Mode and plugging in your recovery image. You can create a recovery image from Chrome OS by browsing to \u003ca href\u003d\"javascript:void(0);\"\u003echrome://imageburner\u003c/a\u003e or follow instructions for other OS on the \u003ca href\u003d\"https://support.google.com/chromebook/answer/1080595?hl\u003den\"\u003eChrome OS help center\u003c/a\u003e site.\u003c/p\u003e\r\n\u003cp\u003eYou can build and run Chromium OS on your Toshiba CB30 (versions R32 and later). Follow the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/quick-start-guide\"\u003equick start guide\u003c/a\u003e to setup a build environment. The board name for the Toshiba CB30 is \"leon\". Build an image and write it to a USB stick or SD card.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eTo boot your image you will first need to enable booting developer signed images from USB (or SD card). Switch your machine to Developer mode and get to a shell by either via VT2 (Ctrl+Alt+F2) and logging in as root or by logging in as a user (or guest mode), starting a \"crosh\" shell with Ctrl+Alt+t, and typing \"shell\". Now run \"sudo crossystem dev_boot_usb\u003d1\" and reboot \"sudo reboot\".\u003c/p\u003e\r\n\u003cp\u003ePlug your USB stick or SD card in and on the scary \"OS Verification is OFF\" screen hit Ctrl+u to boot from external media. If all goes well you should see a \"Chromium OS\" logo screen. If you want to install your build to the SSD, open a shell and type \"sudo /usr/sbin/chromeos-install\". Note: This will replace EVERYTHING on your SSD. Use a recovery image if you want to get back to a stock Chrome OS build.\u003c/p\u003e\r\n\u003cp\u003eHave fun!\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-leon-4389.61.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-leon-4389.61.B\u003c/code\u003e branches.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Disclaimer\" /\u003eDisclaimer\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to your Chromebook's hardware or software are not supported by Google, may compromise your online \u003c/b\u003e\u003cb\u003esecurity\u003c/b\u003e\u003cb\u003e, and may void your warranty....now on to the fun stuff.\u003c/b\u003e\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-Inside-\" /\u003eWhat's Inside?\u003c/h2\u003e\r\n\u003cp\u003eTaking apart your Chromebook is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center. Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first.\u003c/p\u003e\r\n\u003cp\u003eThe location of the firmware write protection disable screw is indicated by the red arrow below.  Remove the screw, and underneath may be a metallic sticker. Remove the sticker (if present) so that the two pads are separated, as in the picture below. Then, boot the system and run \"flashrom --wp-disable\" to enable writing to the write protected regions of flash.\u003c/p\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/toshiba-cb30-chromebook/chromebook_leon_write_protect.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"295\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1393184236986/chromium-os/developer-information-for-chrome-os-devices/toshiba-cb30-chromebook/chromebook_leon_write_protect.jpg\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/toshiba-cb30-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5581542598653454687"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9041942356411587249/14"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5581542598653454687"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5581542598653454687"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$pageName":{"$t":"toshiba-cb30-chromebook"},"sites$revision":{"$t":"10"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/745944246865384491"},"published":{"$t":"2015-06-12T16:31:00.568Z"},"updated":{"$t":"2015-06-12T16:31:00.599Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T16:31:00.568Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-06-12 at 5.30.33 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/745944246865384491"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7348747059329133392"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/memory/Screen%20Shot%202015-06-12%20at%205.30.33%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/745944246865384491"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/745944246865384491"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/745944246865384491"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/745944246865384491"}],"author":[{"name":{"$t":"Primiano Tucci"},"email":{"$t":"primiano@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1550966631093788816"},"published":{"$t":"2015-06-12T16:21:50.758Z"},"updated":{"$t":"2015-06-12T16:21:50.789Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-12T16:21:50.758Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"memory_infra_logo.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1550966631093788816"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7348747059329133392"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/memory/memory_infra_logo.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1550966631093788816"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1550966631093788816"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1550966631093788816"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1550966631093788816"}],"author":[{"name":{"$t":"Primiano Tucci"},"email":{"$t":"primiano@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1530747090825883366"},"published":{"$t":"2015-06-08T16:18:43.242Z"},"updated":{"$t":"2015-06-08T16:18:43.276Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-08T16:18:43.242Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Web MIDI design overview (1).png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1530747090825883366"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7650369345439487952"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/web-midi/Web%20MIDI%20design%20overview%20(1).png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1530747090825883366"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1530747090825883366"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1530747090825883366"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1530747090825883366"}],"author":[{"name":{"$t":"Takashi Toyoshima"},"email":{"$t":"toyoshim@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3839913716752532282"},"published":{"$t":"2015-06-08T16:11:51.815Z"},"updated":{"$t":"2015-06-08T16:11:51.879Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-08T16:11:51.815Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Web MIDI design overview.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3839913716752532282"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7650369345439487952"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/web-midi/Web%20MIDI%20design%20overview.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3839913716752532282"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3839913716752532282"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3839913716752532282"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3839913716752532282"}],"author":[{"name":{"$t":"Takashi Toyoshima"},"email":{"$t":"toyoshim@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"WSl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6627159912214651371"},"published":{"$t":"2011-06-22T18:16:21.084Z"},"updated":{"$t":"2015-06-05T20:30:12.363Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-05T20:30:11.203Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Remote Debugging in ChromiumOS"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-See-the-CrOS-developer-guide-for-instructions-on-using-a-script-that-automates-most-of-the-below-steps.\" /\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eSee the \u003ca href\u003d\"http://www.chromium.org/chromium-os/developer-guide#TOC-Remote-Debugging\"\u003eCrOS developer guide\u003c/a\u003e for instructions on using a script that automates most of the below steps.\u003c/span\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Device-Setup\" /\u003eDevice Setup\u003c/h3\u003e\r\n\u003cp\u003eFor details on copying a binary over to your developer device in order to debug it, see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/debugging-tips/host-file-access\"\u003eHost File Access\u003c/a\u003e.\u003c/p\u003e\r\n\u003cp\u003eYou will need to open a port on your device so that gdbserver can be reached by gdb:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#660000\"\u003esudo /sbin/iptables -A INPUT -p tcp --dport 1234 -j ACCEPT\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eOn the target device, run gdbserver. You can run it with a new process or attach to an existing process:\u003c/font\u003e\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"font-family:monospace;color:rgb(102,0,0)\"\u003egdbserver :1234 /bin/ls        # Debug a new instance of /bin/ls\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,0);font-family:monospace\"\u003egdbserver --attach :1234 6301  # Attach to existing process with pid: 6301\u003cbr /\u003e\u003c/span\u003e\u003cfont color\u003d\"#660000\" face\u003d\"monospace\"\u003egdbserver --attach :1234 $(pgrep chrome -P $(pgrep session_manager))  # Attach to primary chrome browser process\u003c/font\u003e\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Host-Setup\" /\u003eHost Setup\u003cbr /\u003e\r\n\u003c/h3\u003e\r\nBuild a cross-gdb on your host machine (inside the chroot).\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003esudo USE\u003dexpat emerge cross-i686-pc-linux-gnu/gdb         # (x86)\u003cbr /\u003esudo USE\u003dexpat emerge cross-x86_64-cros-linux-gnu/gdb     # (amd64)\u003cbr /\u003esudo USE\u003dexpat emerge cross-armv7a-cros-linux-gnueabi/gdb # (arm)\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eRun gdb and set the appropriate paths to sysroot and debug symbols:\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003ei686-pc-linux-gnu-gdb\u003c/font\u003e\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e(gdb) set sysroot /build/x86-alex\u003cbr /\u003e\r\n\u003c/code\u003e\u003ccode\u003e\u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;color:rgb(0,0,0)\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e(gdb) \u003c/code\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003eset solib-absolute-prefix /build/x86-alex\u003c/code\u003e\u003c/span\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;color:rgb(0,0,0)\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e(gdb) set solib-search-path /build/x86-alex\u003cbr /\u003e\r\n\u003c/code\u003e\u003c/span\u003e(gdb) \u003c/code\u003e\u003ccode\u003eset debug-file-directory /build/x86-alex/usr/lib/debug\u003cbr /\u003e\r\n\u003c/code\u003e\u003ccode\u003e(gdb) \u003c/code\u003e\u003ccode\u003efile /build/x86-alex/bin/ls\u003cbr /\u003e\r\n\u003c/code\u003e\u003ccode\u003e(gdb) \u003c/code\u003e\u003ccode\u003etarget remote 12.34.56.78:1234\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\u003cdiv\u003eIf you want to debug a chrome build with cros_chrome_make, first install to a temporary directory:\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003ecros_chrome_make --install\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif\"\u003eAnd use the following instead (the binary specified in the file command is the one you want to copy over):\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif\"\u003e\u003ccode\u003e(gdb) \u003c/code\u003e\u003ccode\u003eset debug-file-directory /build/x86-alex/tmp/portage/chromeos-base/chromeos-chrome-9999/image/usr/lib/debug\u003cbr /\u003e\u003c/code\u003e\u003ccode\u003e(gdb) \u003c/code\u003e\u003ccode\u003efile /build/x86-alex/tmp/portage/chromeos-base/chromeos-chrome-9999/image/opt/google/chrome/chrome\u003cbr /\u003e\u003c/code\u003e\u003ccode\u003e(gdb) \u003c/code\u003e\u003ccode\u003etarget remote 12.34.56.78:1234\u003c/code\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003eThe program is now paused and you have control over it from your host machine. To start execution:\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e(gdb) continue\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eHelpful hint: you can place the above commands into a file and use the GDB \"source\" command to read it:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eset sysroot /build/x86-alex\u003cbr /\u003e\r\nset solib-absolute-prefix /build/x86-alex\u003c/code\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eset solib-search-path /build/x86-alex\u003c/code\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\r\nset debug-file-directory /build/x86-alex/usr/lib/debug\u003cbr /\u003e\r\nfile /build/x86-alex/opt/google/chrome/chrome\u003cbr /\u003e\r\n# You can include setting breakpoints you know you're going to need.\u003cbr /\u003e\r\nb ChromeMain\u003cbr /\u003e\r\ntarget remote 12.34.56.78:1234\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThen save that as a file (e.g. \"remote.gdb\") and do this:\r\n\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003ei686-pc-linux-gnu-gdb\u003c/font\u003e\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e(gdb) source remote.gdb\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Additional-notes-for-remote-debugging-Chrome-on-ChromeOS\" /\u003eAdditional notes for remote debugging Chrome on ChromeOS\u003c/h3\u003e\u003cdiv\u003eTo get line number info in chrome builds (\u003cb\u003eNote\u003c/b\u003e: don't use FEATURES\u003d\"nostrip\" - the resulting binary will not fit on the device!)\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003eexport KEEP_CHROME_DEBUG_SYMBOLS\u003d1 REMOVE_WEBCORE_DEBUG_SYMBOLS\u003d1\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo debug the installed chrome from outside the chroot (e.g. from emacs) using /usr/bin/gdb + gdbserver on the device as described above, in .gdbinit (or sourced file):\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eset sysroot ~/chromeos/chroot/build/\u003c/code\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003ex86-alex\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eset solib-absolute-prefix ~/chromeos/chroot/build/\u003c/code\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003ex86-alex\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eset debug-file-directory ~/chromeos/chroot/build/x86-alex/usr/lib/debug\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003efile ~/chromeos/chroot/build/x86-alex/opt/google/chrome/chrome\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003etarget remote 172.31.55.210:1234\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo debug chrome built with emerge or cros_chrome_make without installing, as above except:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003efile ~/chromeos/chroot/var/cache/chromeos-chrome/chrome-src/src/out_x86-alex/Release/chrome\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/remote-debugging"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6627159912214651371"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6627159912214651371"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6627159912214651371"}],"author":[{"name":{"$t":"Raymes Khoury"},"email":{"$t":"raymes@chromium.org"}}],"sites$pageName":{"$t":"remote-debugging"},"sites$revision":{"$t":"20"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8754615608142383673"},"published":{"$t":"2009-11-19T17:03:16.510Z"},"updated":{"$t":"2015-06-05T05:12:16.328Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-05T05:12:14.557Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Protecting Cached User Data"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-2\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Abstract\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eAbstract\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Problem:-Multiple-users-portable-de\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eProblem:  Multiple users, portable devices, locally stored data\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Solution:-Encryption\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eSolution:  Encryption\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-encryption-works\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHow encryption works\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Details\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eDetails\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Performance-concerns\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003ePerformance concerns\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Reclaiming-lost-space\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eReclaiming lost space\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Managing-encryption-keys\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eManaging encryption keys\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Hashing-the-user-name\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eHashing the user name\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Password-change-and-offline-login\"\u003e\u003cstrong\u003e8 \u003c/strong\u003ePassword change and offline login\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Password-change\"\u003e\u003cstrong\u003e8.1 \u003c/strong\u003ePassword change\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Offline-login\"\u003e\u003cstrong\u003e8.2 \u003c/strong\u003eOffline login\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Encrypting-swap-and-temporary-data\"\u003e\u003cstrong\u003e9 \u003c/strong\u003eEncrypting swap and temporary data\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-zram-swap\"\u003e\u003cstrong\u003e9.1 \u003c/strong\u003ezram swap\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Error-conditions\"\u003e\u003cstrong\u003e10 \u003c/strong\u003eError conditions\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disk-speed-and-battery-life\"\u003e\u003cstrong\u003e11 \u003c/strong\u003eDisk speed and battery life\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Directory-structure\"\u003e\u003cstrong\u003e12 \u003c/strong\u003eDirectory structure\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Appendix-A:-Formal-requirements\"\u003e\u003cstrong\u003e13 \u003c/strong\u003eAppendix A: Formal requirements\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Appendix-D:-Designs-considered\"\u003e\u003cstrong\u003e14 \u003c/strong\u003eAppendix B: Designs considered\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Appendix-E:-Threats\"\u003e\u003cstrong\u003e15 \u003c/strong\u003eAppendix C: Threats\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Abstract\" /\u003eAbstract\u003c/h2\u003e\r\n\u003cul\u003e\u003cli\u003eChromium OS devices are intended to be both portable and safely shared. As a result, privacy protection for user data stored on the local disk is a requirement for a Chromium-based OS.\u003c/li\u003e\u003cli\u003ePrivacy protection for user data stored on a local disk is accomplished via system-level encryption of users' home directories.\u003c/li\u003e\u003cli\u003eChromium OS uses the \u003ca href\u003d\"https://launchpad.net/ecryptfs\" rel\u003d\"nofollow\"\u003eeCryptfs\u003c/a\u003e stacked filesystem with per-user vault directories and keysets to separate and protect each user’s cached data.\u003c/li\u003e\u003cli\u003eChromium OS devices may use the Trusted Platform Module (TPM) to protect against brute-force attempts to recover a user’s keyset (and therefore the data it protects).\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Problem:-Multiple-users-portable-de\" /\u003eProblem:  Multiple users, portable devices, locally stored data\u003c/h2\u003e\r\n\r\n\u003cdiv\u003e\r\n\u003cp\u003eChromium OS should provide privacy protection for user data stored on the local disk. In particular, some subset of a user's email, pictures, and even HTTP cookies will be stored on the local drive to enhance the online experience and ensure Chrome notebooks are useful even when an Internet connection isn't available. Without this protection, anyone who has physical access to the Chromium OS device would be able to access any data cached on it.\u003c/p\u003e\u003cp\u003eNormally, data stored in the cloud is protected by privacy-guarding mechanisms provided by the servers that host it. When data is pulled out of the cloud, it moves outside of the reach of those server-provided protections. Even though this is the case today with most computers, there are two areas that make this even more important to Chromium OS:\u003c/p\u003e\u003cul\u003e\u003cli\u003eWith a Chromium OS device, users shouldn't have to worry about whether other users of the same device can see their cached data. For example, if my friend wants to log in to my device to check her mail, it's not a big deal. She won't be able to access my data, and even though she used my device, I won't be able to access her data.\u003c/li\u003e\u003cli\u003eChromium OS devices are portable. The risk with very portable devices is that they are easy to misplace or leave behind. We don't want the person who finds a device to instantly have access to every users’ websites, emails, pictures, and so on.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Solution:-Encryption\" /\u003eSolution:  Encryption\u003c/h2\u003e\u003cdiv\u003eSince Chromium OS is built on Linux, we can leverage existing solutions for \u003ca href\u003d\"http://en.wikipedia.org/wiki/Disk_encryption_theory\" rel\u003d\"nofollow\"\u003eencrypting\u003c/a\u003e the user's data at the underlying operating system level and make sure it is automatic and mandatory.  Given the available implementation choices, many possible approaches were considered (see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/protecting-cached-user-data#Appendix_D_Designs_considered\"\u003eAppendix B\u003c/a\u003e for details). Of those approaches, we chose a solution that provides file system-level encryption of \u003ca href\u003d\"http://en.wikipedia.org/wiki/Home_directory\" rel\u003d\"nofollow\"\u003ehome directories\u003c/a\u003e for each user on a device.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eEncrypting each user's home directory means that all of the data stored and cached while browsing will be encrypted by default. In addition, data created and maintained by plugins, like \u003ca href\u003d\"http://www.adobe.com/products/flash/\" rel\u003d\"nofollow\"\u003eAdobe Flash\u003c/a\u003e, will be transparently encrypted without developers or users needing to take any special action.  The same goes for any data stored by HTML5-enabled web applications.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eExisting Operating Systems rely on file ownership and access permissions to prevent two users of a system from accessing each other’s files.  However, the root or administrative user typically can still access any of these files, and the files are really only protected as long as that Operating System instance is booted.  Mounting the drive as a secondary disk would allow full access.  Encryption is a better solution to this problem--even when the device is in the hands of a malicious individual, that person would still have to recover the encryption keys to be able to access the cached data.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-encryption-works\" /\u003eHow encryption works\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"How_does_it_work_\" /\u003e\u003c/h4\u003e\r\n\u003cp\u003eIn a nutshell, each user gets a unique “vault” directory and keyset that is created at her first login.  The vault is used as the underlying encrypted storage for her data.  The keyset is tied to her login credentials and is required to allow the system to both retrieve and store information in the vault.  The vault is opened transparently to the user at login.  On logout or reboot, the user's data is locked away again.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Details\" /\u003eDetails\u003c/h3\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Uh_okay_How_does_it_really_wor\" /\u003e\u003c/h4\u003e\u003cdiv\u003eEach user is allocated a vault directory that contains the encrypted backing storage for their home directory.  The vault is located in a directory specific to the user using a hash of the user name with a salt value, and is mounted using eCryptfs at login to the user directory.  A user-specific file encryption key (FEK) and file name encryption key (FNEK) allow eCryptfs to transparently encrypt and decrypt while the vault is mounted.  A successful mount of the vault is a required step in the login process of Chromium OS.  On first login, /etc/skel/ is copied to the new home directory, and then it's ready for use.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe FEK and FNEK (together, with some additional data, called the keyset) for a user are created using the randomness generator provided by the kernel, which, on Chromium OS devices, is given additional entropy from the TPM at boot.  These 128-bit AES keys are used to encrypt the file contents and file names, respectively.  As a stacked filesystem, eCryptfs has a lower file (the encrypted, persistent file located in the vault and stored on disk) for each upper file (the plaintext file presented at the mount point, which is never stored directly to disk).  The keys exist in kernel memory for the lifetime of the mount.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eA user’s keyset never changes unless their account is removed from the Chromium OS device, or if the system is erased, such as when a recovery device is used.  It must be protected from disclosure and only available with valid login credentials.  To achieve this, Chromium OS uses one of two methods to store the keyset, depending on whether a TPM is available and initialized.  The preferred method involves using the TPM, with the fallback method using the \u003ca href\u003d\"http://www.tarsnap.com/scrypt.html\" rel\u003d\"nofollow\"\u003eScrypt\u003c/a\u003e encryption library.  Both methods tie the user’s vault keyset to their Google Accounts password, and are described further below.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAll of this is managed by one daemon, cryptohomed, which listens for incoming requests from the login manager. If the request is to mount an encrypted vault, the user name and weak password hash must be included. If the request is to unmount the image, cryptohomed clears the keys stored by the kernel and unmounts the vault.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Performance-concerns\" /\u003ePerformance concerns\u003c/h3\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Isn_t_it_incredibly_slow_to_cr\" /\u003e\u003c/h4\u003e\u003cdiv\u003eAdding cryptography to a filesystem comes at a cost--encryption consumes both CPU cycles and additional memory pages.  The latter is primarily managed the the Linux page cache, but the former can result in reads and writes being CPU-bound rather than I/O-bound.  Based on testing compared to I/O direct to the solid state disk, we’ve found the current overhead to be acceptable, though there is always room to be better.  Chromium OS uses encryption to protect cached user data, which does include some frequently used items such as the browser cache and databases, but does not include shared Operating System files and programs.  So while there is a performance cost, it does not apply to all disk I/O.\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Reclaiming-lost-space\" /\u003eReclaiming lost space\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"So_that_part_is_fast_enough_I_\" /\u003e\u003c/h4\u003e\u003cdiv\u003eBeing a stacked filesystem, eCryptfs has a side effect of having a single lower file for every upper file.  This allows for “passthrough”--where a file or directory is created as plaintext in the underlying vault folder, and shows up in the upper mount point.  Generally, this is not a good idea for files (we wouldn’t want to store plaintext data on disk), but for directories, it has a nice benefit of allowing offline file cleanup.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSpecifically, passthrough directories allow a plaintext directory name to show up in the vault, but the directory contents (files, subdirectories, etc.) are still encrypted.  Chromium OS can create passthrough directories for discardable information, such as the browser cache.  Since the name is a standard location, reclaiming disk space when it is low is simply a matter of removing the known cache directory names from each vault that exists on the system.  Without passthrough directories, each vault would have to be mounted (requiring each user’s credentials) to be able to identify the cache directory and delete it.\u003c/div\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ca name\u003d\"managingkeys\" /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Managing-encryption-keys\" /\u003eManaging encryption keys\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Going_back_what_do_you_mean_by\" /\u003e\u003c/h4\u003e\u003cdiv\u003eAs mentioned earlier, the user’s vault keyset is ultimately protected by a partial cryptographic hash of the user's passphrase. A partial cryptographic hash is used because the user's Google Accounts password must not be exposed to offline attack. Instead, we're willing to lose some of the entropy supplied by the passphrase by performing a SHA-256 digest of a user-specific salt concatenated with the user's passphrase. The first 128 bits of the digest are used as the user's \"weak password hash.\"\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOften, user passwords will only contain anywhere from \u003ca href\u003d\"http://en.wikipedia.org/wiki/Password_strength#Human-generated_passwords\" rel\u003d\"nofollow\"\u003e18 bits to 30 bits of entropy\u003c/a\u003e starting at 8 characters in length. Spreading that entropy over a hash and halving it is not really that great. At the very least, adding a salt means that it will be quite costly to precompute a dictionary of hashes, but that still isn't perfect if an attacker has the time and access to the local salt in order to attempt to brute force the local password. There are two other useful options that can be pursued to help dissuade offline attacks. The first is that \u003ca href\u003d\"http://en.wikipedia.org/wiki/Key_strengthening\" rel\u003d\"nofollow\"\u003ekey strengthening\u003c/a\u003e can be used to increase the amount of time it takes to calculate a hash from a dictionary-based brute force attack that uses repeated passes through a cryptographic hash. The other option is to make use of a TPM device when it is present, such as in Chromium OS devices. This allows the TPM to effectively rate limit brute force attacks without the overhead of key strengthening.  \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs mentioned above, both Scrypt-based and TPM-based protection may be employed.  We’ll describe the Scrypt method first, being the simpler of the two.  The benefit of using Scrypt is that it uses a unique method of password strengthening to derive a key for the encryption that is both CPU- and memory-bound, making a parallelized brute-force attack more costly than a scheme such as repeated hash rounds.  Scrypt is used to directly protect the vault keyset using a key based on the strengthened user’s password (actually the user’s weak password hash).  The encrypted keyset is stored on disk, and is unlocked for use at login when valid credentials allow for it to be decrypted.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe preferred method of protecting the vault keyset involves the TPM to protect against brute force attacks.  The method takes advantage of the secure key storage functionality of the TPM (and the relatively slow clock speed of the chip) to protect the keyset.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen using the TPM, Chromium OS creates a system-wide RSA key using OpenSSL and then wraps it with the TPM’s Storage Root Key on first boot.  The original key is destroyed, and we are left with an RSA key whose private key is known only on-chip on the TPM.  This means that, short of a vulnerability in the TPM, in order to use this RSA key, the private key operation must happen on this specific TPM, so mechanisms that use it are better protected against brute-force attacks.  Furthermore, as current TPMs can take around half a second for a private key operation, even attacks which use the TPM are effectively rate limited.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe use a system-wide key rather than per-user key for two important reasons: first, key load into the TPM is costly (it must decrypt the private key component).  While 0.5s is a tolerable penalty to pay for the private key operation, longer (which would be the case if we had to load a user-specific key on each login attempt) is a noticable impact on user login.  Using a system-wide key allows one key to be loaded and generally left in the TPM while the system is booted.  Since it is protected by the chip, this is okay.  Second, the typical method of incorporating user passwords with keys on the TPM is to require authentication for their use.  This would be a good solution for Chromium OS, but there is a downside.  TPMs feature a vendor-specific dictionary attack defense mode, which is easily entered into with too many failed TPM authentications.  On many chips, this mode is aggressive, and once entered, renders the chip useless for some amount of time.  Since failed passwords happen (both legitimately, and by an attacker), too many failed passwords would leave the TPM disabled for a time, and the vaults it protected unusable.  Instead, we use a passwordless system-wide key, but mix the user’s password in a unique way that achieves the same benefits without the possibility of entering this mode.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSpecifically, when a vault keyset is encrypted, the following process takes place:\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eA 256-bit AES vault keyset key (VKK below) is created randomly and used to encrypt the vault keyset.  The encrypted vault keyset is stored to disk.  This intermediate key is used to allow the vault keyset to be larger than a single RSA operation would allow for.\u003c/li\u003e\u003cli\u003eThe VKK is encrypted with the system-wide RSA key previously mentioned (TPM_CHK below), resulting in an intermediate encrypted vault keyset key (IEVKK).\u003c/li\u003e\u003cli\u003eThe final 128 bits of the encrypted blob from step 2 are encrypted in place using the user’s weak password hash which has first been hashed a keyset-specific salt.  This is done using a single AES operation with no padding, allowing for no verification on decrypt.  The result is the encrypted vault keyset key (EVKK), which is stored to disk.\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eStep 3 is critical to combining the user’s weak password hash (and therefore preventing anyone with access to the TPM and system-wide RSA key from decrypting the vault keyset).  Unless the attacker acquires the user’s password (or guesses it), the blob passed to the TPM to decrypt using the system-wide key is effectively garbage--the TPM will fail to decrypt because is is effectively corrupt until those final 128 bits are corrected.  The TPM treats this as a failed decrypt (rather than a failed authentication), and the vault keyset key (and vault keyset it protects) cannot be recovered.  This operation is illustrated below:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\" /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/protecting-cached-user-data/ChromiumOS_TPM_Cryptohome.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1291791014176/chromium-os/chromiumos-design-docs/protecting-cached-user-data/ChromiumOS_TPM_Cryptohome.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003eWhile these protection methods result in protecting the cached user data, what they effectively address is preventing an attacker from offline brute-force guessing a user’s Google Accounts password.\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Hashing-the-user-name\" /\u003eHashing the user name\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Why_is_the_username_also_crypt\" /\u003e\u003c/h4\u003e\u003cdiv\u003eThe primary reason for hashing the user name is to make it safe for use on the filesystem without writing a custom mapping of unsafe characters. A web-based user name may contain characters that are not safe for use on the file system. Using a strong hash will give a reasonably unique value that is safe for use on the file system. In addition, if all references to user names outside of the encrypted images are done using a HASH(salt||user@domain.com), then it becomes quite difficult for any user, or attacker, to determine what user names are in use on a given device without attempting a brute force attack. This is a nice side effect, but not an explicit goal.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Password-change-and-offline-login\" /\u003e\u003cfont size\u003d\"4\"\u003e\u003cb\u003ePassword change and offline login\u003c/b\u003e\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003ePassword change and offline login are both handled through cryptohomed.\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Password-change\" /\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003ePassword change\u003c/b\u003e\u003c/font\u003e\u003c/h3\u003e\u003cdiv\u003eIf the user changes her password from another browser, the vault keyset is still tied to the previous password.  Chromium OS allows password change only on a successful online login.  In that case, Google’s web service will authenticate the user with her new credentials, returning a successful condition.  Chromium OS will attempt to mount her vault, but that will fail with a bad decrypt condition.  Since Chromium OS knows the password was in fact correct, it will present the user with the option of entering her old password once (with which it can recover the vault keyset and then re-protect with the new password), or simply re-create the vault from scratch.\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Offline-login\" /\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eOffline login\u003c/font\u003e\u003c/b\u003e\u003c/h3\u003e\u003cdiv\u003eWhen a Chromium notebook is offline, it cannot authenticate a user with Google’s web service.  However, the encrypted vault keyset can be used for offline credential verification.  Put simply, if a given password results in a successful recovery of the vault keyset, the password was correct.  So, when Chromium OS doesn’t detect a network connection, it will attempt to authenticate by mounting the user’s vault directly (this only works if the user has previously logged in while online, and so she has a vault present on the notebook).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Encrypting-swap-and-temporary-data\" /\u003eEncrypting swap and temporary data\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"What_about_encrypting_swap_and\" /\u003e\u003c/h4\u003e\r\n\r\nAt present, Chromium OS devices don't use a swap partition, and temporary data is written to a tmpfs file system that is not backed by any permanent storage (such as disk). If a swap device is needed in the future, we'll explore the challenges associated with protecting that data satisfactorily.\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-zram-swap\" /\u003ezram swap\u003c/h3\u003e\u003cp\u003eWhile newer releases of Chrome OS have started including zram for swap purposes, it is still not stored on disk. zram takes a chunk of memory and uses that for swap. When pages are moved between that swap device, they are compressed/uncompressed on the fly. So there still is no permanent storage in play.\u003c/p\u003e\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Error-conditions\" /\u003eError conditions\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Let_s_back_up_a_bit_What_happe\" /\u003e\u003c/h4\u003e\u003cdiv\u003eYou may be wondering what happens if an error occurs. Is the user locked out? If a user authenticates successfully, but all attempts to create or access an encrypted vault fail, then login may or may not fail.  The answer is dependent on the scenario.  Chromium OS automatically detects unrecoverable failures, and re-creates a user’s vault in the conditions.  These conditions are typically related to the TPM, such as happens if it is cleared (effectively making data protected by it unrecoverable).  Transient failures do not result in a fresh vault, but both types of failures are rare and usually predictable (see our document on TPM use for more information).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRegardless, the user can always log in to the device as a guest.  While it does not provide access to the encrypted user data, and the session history is not stored, it does always allow use of the system.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Disk-speed-and-battery-life\" /\u003eDisk speed and battery life\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Does_this_kill_the_battery_Wha\" /\u003e\u003c/h4\u003e\r\n\u003cdiv\u003e\u003cdiv\u003eSimple benchmarks indicate that eCryptfs under common browsing patterns does not significantly alter battery life. It's when sustained reads and writes occur that more and more CPU is used, and hence more battery draw. A test with a heavy, sustained write resulted in similar battery discharge rate as the heavy writing used without encryption, but the encrypted large write took about twice as long to complete.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn most use cases, disk encryption isn't noticeable. If AES acceleration reaches additional processors, then the impact will be even lower.\u003c/div\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Directory-structure\" /\u003eDirectory structure\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Where_does_everything_live_\" /\u003e\u003c/h4\u003e\u003cdiv\u003eAll metadata for this feature will live under the /home/.shadow directory. Each user will have a subdirectory with a name based on the user name hash. That directory will contain all data related to that user's image on the machine. For example:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  /home/.shadow/da39a3ee5e6b4b0d3255bfef95601890afd80709/vault\u003c/div\u003e\u003cdiv\u003e  /home/.shadow/da39a3ee5e6b4b0d3255bfef95601890afd80709/master.0\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe system-wide TPM RSA key is stored in:\u003c/div\u003e\u003cdiv\u003e  /home/.shadow/cryptohome.key\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Appendix-A:-Formal-requirements\" /\u003eAppendix A: Formal requirements\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Appendix_A_Formal_Requirements\" /\u003e\u003c/h4\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe primary objective is to protect sensitive end user data from exposure if the device or drive is lost.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUser data \u003cb\u003eMUST NOT\u003c/b\u003e be accessible when the device is powered down. \u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUser data \u003cb\u003eMUST\u003c/b\u003e be protected when the disk has been removed from a device.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUser data \u003cb\u003eMAY\u003c/b\u003e be protected when the device is suspended.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eGoogle Accounts passphrases \u003cb\u003eMUST NOT\u003c/b\u003e be exposed for direct offline attack.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUser data \u003cb\u003eMUST\u003c/b\u003e be available during offline login.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUser data \u003cb\u003eMUST\u003c/b\u003e be recoverable after an out-of-band password change.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px;text-align:left\"\u003eUser data \u003cb\u003eMUST\u003c/b\u003e \u003cb\u003eNOT\u003c/b\u003e be exposed across users on a multiuser device.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUser data swapped out of memory \u003cb\u003eMAY BE\u003c/b\u003e protected (depending on the requirement below).\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003ePower and performance overhead \u003cb\u003eSHOULD BE\u003c/b\u003e minimized. (Some\r\nconcrete maximum acceptable overhead should be determined. It may end\r\nup being device specific, however. In particular, boot time, login\r\ntime, and Chromium browser responsiveness issues are important.)\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUsers \u003cb\u003eMUST NOT\u003c/b\u003e be able to opt out of encryption.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cbr /\u003e\r\nNon-goals:\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eOffline credential storage behavior may be a side effect of the chosen implementation.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eA TPM device may be used, but it is a non-goal to create a TPM-dependent solution.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eRoot partition encryption/protection is not a goal.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eIt is a non-goal to provide a remote wipe mechanism via this feature, but it may make such a design easier.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Appendix-D:-Designs-considered\" /\u003eAppendix B: Designs considered\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Appendix_D_Designs_considered\" /\u003e\u003c/h4\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003ePer-user block-based encryption\u003c/b\u003e: This approach would use a random key to encrypt a partition per-user that is protected by the user's passphrase (and a Google-held backup key). This approach would ensure that a user's data will be accessible only when the user has logged in, and it allows for easy remote wipe (removing the key for the partition). This does add more pain when it comes to device management. Each data partition would need to be separated into preallocated regions for each simultaneously cached user stored on the system (that is, data_space / n \u003d users_space). \u003cbr /\u003e\r\n\u003ci\u003eNote:\u003c/i\u003e This should not be visible to the user unless he tries to log in with the new passphrase while he is offline.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003ePer-user file system-based encryption\u003c/b\u003e: This approach would make use of encfs, cryptofs, or eCryptfs to add a layered encrypted file system on top of a preconfigured block device. Barring eCryptfs, the performance is quite painful with userland solutions like encfs and cryptofs. eCryptfs provides good performance, and allows for an approach similar to above (guaranteeing per-user privacy and offline defenses) without requiring preallocated block devices per user.\r\n\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eWhole disk encryption with TPM\u003c/b\u003e: This would use a TPM-protected key to unlock a drive. This would mean that with the whole device, the data would be exposed to OS-level attacks once booted, unless some form of pre-boot authentication was used. This is not the user experience we are looking for, and this would expose data trivially to a physical attacker. The disk would only be protected if removed from the device.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eWhole data partition encryption\u003c/b\u003e: This would simplify the space utilization problem by putting all users on one encrypted partition. Normal access controls could keep users out of each other's data, but adding a new user to the encrypted drive without requiring another user to \"authorize\" the new user at login time is a challenge under this scheme. The reason this is an issue is because each user's passphrase-derived key is used to armor the disk encryption key. Even if a user authorizes another user to access the drive, the new user would be required to type the original passphrase immediately (or at next login), or a secondary key would need to be in play to allow for the encryption key to be decrypted and re-encrypted without the first user present. There are no clean ways around this.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nAnother downside to this approach is that if any user is compromised and a privilege escalation vulnerability exists in the system, all user data would be compromised. \u003cbr /\u003e\r\n\u003cbr /\u003e\r\nAdditionally, this approach would complicate any remote-wipe scheme we might implement. Whole-partition encryption would necessitate actual file removal to implement a per-user wipe, instead of just reinitializing the cryptographic file system or full data wipe. If we support only full data wipe, then that would probably be restricted to device owners only, but a per-user wipe would allow a user to clean his own data off a friend's machine he used once. \u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eNo encryption\u003c/b\u003e: Not only would this mean most enterprises can't use the device for work, it also would mean that many users would be unhappy. As is, most people don't want to lose their data if someone steals their device. And regardless of policies, people will use their personal devices at work. We'd like to think that providing simple, effective encryption to the platform is a long-term benefit to everyone.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eChromium browser-only encryption\u003c/b\u003e: Pushing encryption into the Chromium browser was considered.  This approach would ensure that all cached data and all downloaded/accessed data is encrypted. This solution may be pursued in the long term. At present, providing the encryption at the OS level means that it will catch any data external to the Chromium browser (Adobe Flash local storage) and developer data.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eOther interesting side effects\u003c/b\u003e: Both the whole data partition encryption and the per-user encryption come with the benefit of a free offline credential store. A weak hash of the password can be used to protect the stores which would then be checked on mount. In addition, the user can be mapped to a system account using this information. If a user is password slot 1, then he will be mapped to user_1, and so on.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Appendix-E:-Threats\" /\u003eAppendix C: Threats\u003c/h2\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"Appendix_E_Threats\" /\u003e\u003c/h4\u003e\r\n\u003cp style\u003d\"margin:0px\"\u003eThe following list includes the primary threats that are addressed by this design:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker acquires a powered down device with the drive in it and attempts to access all local user home directories.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker acquires a device in suspend state with the drive in it and attempts to extract the encryption key with a cold boot attack.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker with login privileges attempts to access another user's data using a known bug, vulnerability, or workaround.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cbr /\u003e\r\nMany threats are not dealt with through this design:\u003cbr /\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker with a remote compromise will be able to access the currently logged in user's data.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker will be able to access all user data if autologin is enabled and the device is in any state.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker will be able to access all user data if the machine is suspended or logged in and screen locking is disabled.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker will be able to dump all RAM from a suspended machine using a \u003ca href\u003d\"http://en.wikipedia.org/wiki/Cold_boot_attack\" rel\u003d\"nofollow\"\u003ecold boot attack\u003c/a\u003e exposing any credentials in memory and the disk encryption key schedule until that can be fixed.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker who steals a running machine with screen locking will be able to perform screen lock, usb, network, and any other runtime attacks to gain access unless the user is able to initiate a remote wipe while the machine is still Internet-connected.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAn attacker who is able to modify the root partition will be able to compromise the runtime environment leading to data exposure when a user subsequently logs in. Our \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003everified boot process\u003c/a\u003e should help combat this, however.\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/protecting-cached-user-data"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8754615608142383673"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8754615608142383673"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8754615608142383673"}],"author":[{}],"sites$pageName":{"$t":"protecting-cached-user-data"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8117441866373500826"},"published":{"$t":"2015-06-04T20:37:12.939Z"},"updated":{"$t":"2015-06-04T20:37:12.979Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-04T20:37:12.939Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-06-04 at 1.37.00 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8117441866373500826"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/Screen%20Shot%202015-06-04%20at%201.37.00%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8117441866373500826"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8117441866373500826"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8117441866373500826"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8117441866373500826"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2527770834732667026"},"published":{"$t":"2015-06-04T19:47:56.643Z"},"updated":{"$t":"2015-06-04T19:47:56.696Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-04T19:47:56.643Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-06-04 at 12.47.34 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2527770834732667026"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/Screen%20Shot%202015-06-04%20at%2012.47.34%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2527770834732667026"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2527770834732667026"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2527770834732667026"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2527770834732667026"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6882802972022384242"},"published":{"$t":"2015-06-04T19:47:16.928Z"},"updated":{"$t":"2015-06-04T19:47:16.959Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-04T19:47:16.928Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-06-04 at 12.46.58 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6882802972022384242"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/Screen%20Shot%202015-06-04%20at%2012.46.58%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6882802972022384242"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6882802972022384242"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6882802972022384242"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6882802972022384242"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/86271373442201184"},"published":{"$t":"2015-06-04T03:53:26.622Z"},"updated":{"$t":"2015-06-04T03:54:18.083Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-06-04T03:54:12.054Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Polymer 0.8"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Moved-to-Polymer-1.0.\" /\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/polymer-1-0\"\u003eMoved to Polymer 1.0.\u003c/a\u003e\u003c/h2\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/polymer-0-8"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/86271373442201184"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/86271373442201184"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/86271373442201184"}],"author":[{"name":{"$t":"Michael Giuffrida"},"email":{"$t":"michaelpg@chromium.org"}}],"sites$pageName":{"$t":"polymer-0-8"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5615943819485952411"},"published":{"$t":"2015-05-28T17:15:28.371Z"},"updated":{"$t":"2015-05-28T17:15:28.407Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-28T17:15:28.371Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"resources-sw.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5615943819485952411"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5553336162886524501"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/serviceworker/service-worker-faq/resources-sw.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5615943819485952411"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5615943819485952411"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5615943819485952411"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5615943819485952411"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"XSl7JmA5\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4013088826456316651"},"published":{"$t":"2011-11-23T03:53:11.268Z"},"updated":{"$t":"2015-05-21T21:13:14.958Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-21T21:13:13.530Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Kernel rebase notes"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Flow\" /\u003eFlow\u003c/h3\u003e\u003cdiv\u003eA kernel rebase consists of moving sets (ie, topics) of patches from one version to a later version.\u003c/div\u003e\u003cdiv\u003eThe flow is:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eSeparate current patches into topic branches\u003c/li\u003e\u003cul\u003e\u003cli\u003egit cherry-pick individual patches to common branches\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eRebase patches from old kernel version to new kernel version\u003c/li\u003e\u003cul\u003e\u003cli\u003egit rebase $new_version\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eMerge new topics together on the new kernel version\u003c/li\u003e\u003cul\u003e\u003cli\u003egit merge $topics\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003eThis flow is iterative.  It can take a long time to cherry-pick all the changes into topics, then rebase, then merge.  In that time, more changes land which require a second or even third iteration of this sequence.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Estimate-how-long-the-rebase-effort-will-take\" /\u003eEstimate how long the rebase effort will take\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eIt took me 3 months to sort through about 5644 3.14 changes and rebase appropriately to 3.18.  And that was with help.  So I would estimate roughly 434 per week.\u003c/div\u003e\u003cdiv\u003eReally, ramping up on my git knowledge and settling on a set of useful tools took a significant amount of time, too.\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Tools\" /\u003eTools\u003c/h3\u003e\u003cdiv\u003eVarious git commands will be particularly important during the rebase.  gitk is a graphic tool that some folks use, but I used just the git command itself.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003egit log --oneline --first-parent --reverse v3.14..m/master\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003eThis shows all the commits in our tree on top of v3.14.\u003cdiv\u003e--oneline shows just one line per commit: commit hash plus the one line summary.\u003c/div\u003e\u003cdiv\u003e--first-parent shows merge changes, but it excludes merge lineage (ie, all the changes that were actually being merged in).  Merges are rare after the rebase and are typically handled on a case by case basis.\u003c/div\u003e\u003cdiv\u003e--reverse shows the changes in the order they occur (oldest to newest) rather than the default order (newest to oldest).\u003cbr /\u003e\u003cdiv\u003eThese parameters are the most important ones in my rebase (to 3.18).\u003c/div\u003e\u003cdiv\u003ePipe to 'wc -l' shows how many commits you are dealing with.\u003c/div\u003e\u003cdiv\u003eRedirect to a file, say \"gitlog.v3.14..\", lets me examine the list in 'vi'.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003egit show $COMMIT --oneline --name-only\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e--name-only shows the touched files.  This is important in determining which topic a change should be cherry-picked into.\u003cbr /\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eset keywordprg\u003dgit\\ show\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003ein my ~/.vimrc file allows me to 'vi gitlog.v3.14..', position the cursor on the change_id, then \"K\" (the keyword program command in 'vi') runs 'git show' on that change_id.\u003c/div\u003e\u003cdiv\u003eThis is useful for examining change details within the list of changes in which it appears.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003egit rebase --onto master next topic\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003eRebase all changes between next and topic onto master, and move the current branch label (usually topic) to the resulting HEAD.\u003cdiv\u003eThere were a number of times I decided to replay some subset of changes to a new head, and this is the way to do it.  I highly recommending closely examining 'git rebase --help', first.\u003c/div\u003e\u003cdiv\u003eIt will basically say it changes this:\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003e               o---o---o---o---o  master\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                    \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                     o---o---o---o---o  next\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                                      \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                                       o---o---o  topic\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003einto this:\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003e               o---o---o---o---o  master\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                   |            \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                   |             o'--o'--o'  topic\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                    \\\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                     o---o---o---o---o  next\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003eNote that the master and next labels remain unchanged, but topic moves to the rebased HEAD.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eDid you screw up an important branch label with a bad rebase?\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003egit reflog\u003c/code\u003e\u003cbr /\u003e\u003cdiv /\u003e\u003ccode\u003egit reset --hard $change_ID\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003eThe reflog shows recent HEAD changes and the commands that changed them.  The first column is the resulting change_ID.\u003cdiv\u003eThe reset changes the label to the specified change_ID.  --hard restores the files to that version.\u003cbr /\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOverview\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Flow\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eFlow\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Estimate-how-long-the-rebase-effort-will-take\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003eEstimate how long the rebase effort will take\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Tools\"\u003e\u003cstrong\u003e1.3 \u003c/strong\u003eTools\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Topic-Branches\"\u003e\u003cstrong\u003e1.4 \u003c/strong\u003eTopic Branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-kernel-and-kernel-next-Repos\"\u003e\u003cstrong\u003e1.5 \u003c/strong\u003ekernel and kernel-next Repos\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Rebase-process\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eRebase process\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-1:-Add-upstream-mainline-stable-trees\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eStep 1: Add upstream mainline/stable trees\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-2:-Set-up-Topic-branches\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eStep 2: Set up Topic branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-3:-resync-Topic-Branches\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eStep 3: resync Topic Branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-4:-sanity-check-Topic-Branches\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eStep 4: sanity-check Topic Branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-5:-Mark-sync-in-master-branch\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003eStep 5: Mark sync in master branch\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-6:-Create-new-Topic-Branches\"\u003e\u003cstrong\u003e2.6 \u003c/strong\u003eStep 6: Create new Topic-Branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-7:-Rebase--base-Topic-branch-first\"\u003e\u003cstrong\u003e2.7 \u003c/strong\u003eStep 7: Rebase -base Topic branch first\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Handling-Rebase-Conflicts\"\u003e\u003cstrong\u003e2.7.1 \u003c/strong\u003eHandling Rebase Conflicts\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Debugging-Boot\"\u003e\u003cstrong\u003e2.7.2 \u003c/strong\u003eDebugging Boot\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-8:-Push--base-Topic-Branch\"\u003e\u003cstrong\u003e2.8 \u003c/strong\u003eStep 8: Push -base Topic Branch\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-9:-Rebase-other-Topic-branches\"\u003e\u003cstrong\u003e2.9 \u003c/strong\u003eStep 9: Rebase other Topic branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-10:-Merge-Topic-Branches\"\u003e\u003cstrong\u003e2.10 \u003c/strong\u003eStep 10: Merge Topic Branches\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-11:-Test-Merged-Branch\"\u003e\u003cstrong\u003e2.11 \u003c/strong\u003eStep 11: Test Merged Branch\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-12:-Change-the-manifests-for-kernel-next.git-and-ask-for-help\"\u003e\u003cstrong\u003e2.12 \u003c/strong\u003eStep 12: Change the manifests for kernel-next.git and ask for help\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-13:-Move-over-to-kernel.git-and-change-those-manifests\"\u003e\u003cstrong\u003e2.13 \u003c/strong\u003eStep 13: Move over to kernel.git and change those manifests\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Step-14:-Wait-and-debug\"\u003e\u003cstrong\u003e2.14 \u003c/strong\u003eStep 14: Wait and debug\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Important-notes\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eImportant notes\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cfont size\u003d\"5\"\u003eSource organization\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Topic-Branches\" /\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eTopic Branches\u003c/font\u003e\u003c/b\u003e\u003c/h3\u003e\r\n\u003cp\u003eThe key to sanity when doing this is to do good topic branch split-ups. This reduces the scope of each branch to only cover a specific part of the kernel, or a specific set of functionality. \u003cb\u003e\u003ci\u003eMultiple,smaller topic branches allow faster iterations.\u003c/i\u003e\u003c/b\u003e  The following branches are in use for v3.0 and v3.2 rebase:\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-top-color:rgb(136,136,136);border-right-color:rgb(136,136,136);border-bottom-color:rgb(136,136,136);border-left-color:rgb(136,136,136);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:172px;height:68px\"\u003e chromeos-base-\u0026lt;version\u0026gt;\u003c/td\u003e\r\n\u003ctd style\u003d\"width:497px;height:68px\"\u003eThis branch contains more or less all base changes we need to run ChromeOS on an x86 system: EFI, ACPI changes, build infrastructure, configs, and some of the chromeos-specific drivers we have picked up (should be very few left)\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:172px;height:37px\"\u003echromeos-misc-\u0026lt;version\u0026gt;\u003c/td\u003e\r\n\u003ctd style\u003d\"width:497px;height:37px\"\u003eKitchen sink for backported patches and misc other changes. It can sometimes be hard to decide what goes here vs in -base.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:172px;height:15px\"\u003e chromeos-gobi-\u0026lt;version\u0026gt;\u003c/td\u003e\r\n\u003ctd style\u003d\"width:497px;height:15px\"\u003eOur driver changes for qcserial and gobi. Given that gobi drivers have been rejected upstream we might have to carry this for the long run.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:172px;height:15px\"\u003e chromeos-verity-\u0026lt;version\u0026gt;\u003c/td\u003e\r\n\u003ctd style\u003d\"width:497px;height:15px\"\u003e Verity device mapper module. This branch should hopefully go away once the patches have been accepted upstream.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:172px;height:15px\"\u003e chromeos-tegra-\u0026lt;version\u0026gt;\u003c/td\u003e\r\n\u003ctd style\u003d\"width:497px;height:15px\"\u003eAll the Nvidia ARM Tegra changes. Quite a stack of patches that are slowly going upstream.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:172px;height:15px\"\u003e chromeos-input-\u0026lt;version\u0026gt;\u003c/td\u003e\r\n\u003ctd style\u003d\"width:497px;height:15px\"\u003e Mouse/Touch/trackpad and related subsystem drivers (e.g. multi-touch support).\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/blockquote\u003eUpdate from my 3.14-3.18 experience:\u003cdiv\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-color:rgb(136,136,136);border-width:1px\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"width:220px;height:14px\"\u003e chromeos-base-\u0026lt;version\u0026gt;\u003c/td\u003e\u003ctd style\u003d\"width:496px;height:14px\"\u003e chromeos/config and chromeos/scripts changes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:220px;height:14px\"\u003e chromeos-misc-\u0026lt;version\u0026gt;\u003c/td\u003e\u003ctd style\u003d\"width:496px;height:14px\"\u003e Miscellaneous software related patches: futex, ftrace, time, genalloc, FS, etc.\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:220px;height:29px\"\u003e chromeos-platform-\u0026lt;version\u0026gt;\u003c/td\u003e\u003ctd style\u003d\"width:496px;height:29px\"\u003e Similar to misc, but more hardware specific.  power, suspend, irq, NAND, MMC, MTD, ACPI, IIO, etc.\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:220px;height:48px\"\u003e chromeos-drm-\u0026lt;version\u0026gt;\u003c/td\u003e\u003ctd style\u003d\"width:496px;height:48px\"\u003e drivers/gpu/drm and related changes.  For 3.18, we dropped all 3.14 patches, and\u003cbr /\u003eStephane provided a new set for 3.18.\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003eAdd new topic branches where there is active development. e.g. we might add chromeos-wifi-\u0026lt;version\u0026gt; for wifi drivers since they have plenty of backports.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-kernel-and-kernel-next-Repos\" /\u003ekernel and kernel-next Repos\u003c/h3\u003e\r\n\u003cdiv\u003eToday we have two kernel repos: kernel and kernel-next. The historical reason is repo tools don't allow to track two branches of one git repo in two locations in the directory structure. We needed two different base versions for quite a while -- one for x86 and one for ARM. We have since merged the bases, but \"kernel-next\" tree is still around.\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe overview of the steps I work with the repos is:\u003cbr /\u003e\r\n\u003col\u003e\u003cli\u003eDo the original topic-branch split-up in the kernel.git repo since the patches reside on the main branch.\u003c/li\u003e\r\n\u003cli\u003eMove the topic branches to the kernel-next repo and do all the rebase work in kernel-next repo.\u003c/li\u003e\r\n\u003cli\u003eMerge the topic branches together to a combined branch and ask others to test the combined branch in kernel-next repo. \u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eWarn \"Testers\" the topic-branches will get rebased and to NOT keep significant work on top of kernel-next combined branch.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Rebase-process\" /\u003e\u003cfont size\u003d\"5\"\u003eRebase process\u003c/font\u003e\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-1:-Add-upstream-mainline-stable-trees\" /\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eStep 1: Add upstream mainline/stable trees\u003c/font\u003e\u003c/b\u003e\u003c/h3\u003e\r\n\u003cdiv style\u003d\"font-family:courier new,monospace;margin-left:40px\" /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv style\u003d\"font-family:courier new,monospace;margin-left:40px\"\u003e\u003ccode\u003egit remote add mainline git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:courier new,monospace;margin-left:40px\"\u003e\u003ccode\u003egit remote add linux-stable git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003egit remote update mainline\u003cbr /\u003e\u003c/font\u003e\r\n\u003ccode style\u003d\"font-family:courier new,monospace\"\u003egit remote update linux-stable\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThis makes \"interesting\" tags available from upstream sources. This step can be done at any time before we need to use tags in upstream repos.\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-2:-Set-up-Topic-branches\" /\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eStep 2: Set up Topic branches\u003c/font\u003e\u003c/b\u003e\u003c/h3\u003e\r\n\u003cdiv\u003eSplitting the tree up into topic branches is something that you rarely have to do from scratch. This document will assume those exist.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eMaintain the topic branches over time, syncing up from the main tracking branch every now and then and pushing them to the server. \u003ci\u003eOthers should NOT base their work off of the topic branches.\u003c/i\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n'git-new-workdir'  checks out a specific branch into a new directory but uses the same backing .git object storage. This allows us to check out each topic branch into one directory per topic and we won't have to sync up the .git contents when done.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cb\u003eWARNING: NEVER use git-new-workdir for a branch that you have checked out somewhere else, it is a recipe for disaster.\u003c/b\u003e  In other words, delete the \"split\" directory (and it's children) created below before checking out any of the topic branches in some other location.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eUnder \u003cspan style\u003d\"font-family:courier new,monospace\"\u003esrc/third_party/kernel/\u003c/span\u003e , build the \"topic branches\":\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\r\n\u003cdiv style\u003d\"margin-left:40px;font-family:courier new,monospace\" /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv style\u003d\"margin-left:40px;font-family:courier new,monospace\"\u003e\u003ccode\u003ecd src/third_party/kernel\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003emkdir split\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003ecd split\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003efor d in base gobi misc verity tegra ; do\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-left:40px;font-family:courier new,monospace\"\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003ccode\u003e/usr/share/git/contrib/workdir/git-new-workdir  ../../../../.repo/projects/src/third_party/kernel/files.git ${d} cros/chromeos-${d}-3.0\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003ecd ${d}\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit checkout -b chromeos-$d-3.0 cros/chromeos-$d-3.0\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003ecd ..\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003edone\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\nIn case not all the topic branches are based on the same tree, run:\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit rebase --onto v3.0 v3.0.3 HEAD\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\nin order to rebase all changes in \"HEAD\" from v3.0.3 back to v3.0.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThen open one terminal window for each topic \r\nbranch and two extra windows:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003eadd \u003cfont face\u003d\"'courier new', monospace\"\u003e\u003ccode\u003ealias gp\u003d\"git cherry-pick\"\u003c/code\u003e\u003c/font\u003e to ~/.bash_profile in the chroot (used below to shorten the command lines)\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eIn the first 5 windows, cd into one of the 5 topic branch directories.\u003c/li\u003e\r\n\u003cli\u003eIn the 6th window, to run/view \u003cspan style\u003d\"font-family:courier new,monospace\"\u003egit log \u003cspan style\u003d\"font-family:arial,sans-serif\"\u003ecommand (listed below)\u003c/span\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eUse the 7th for misc git commands to determine where conflicts are coming from, etc.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIn the 6th window \u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003efind the \"sync point\" (last commit that was cherry picked) with:\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/p\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit log --oneline cros/chromeos-3.0\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003eand search for \"Merge\".\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e The \"sync point\" commit should look something like:\u003c/font\u003e\u003cbr /\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003cspan\u003e    \u003c/span\u003ee8f848b Merge branches 'chromeos-base-3.0', 'chromeos-misc-3.0', 'chromeos-verity-3.0', 'chromeos-gobi-3.0' and 'chromeos-tegra-3.0' into chromeos-3.0\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eOne can also look at \"git log\" for each of the topic branches to find out the last cherry-picks into each of those and confirm the SHA1 \u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ematches.\u003c/font\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-3:-resync-Topic-Branches\" /\u003e\u003cfont size\u003d\"3\"\u003eStep 3: resync Topic Branches\u003c/font\u003e\u003c/h3\u003e\r\n\u003cp\u003e\r\nNext, produce a list of commits that need to be cherry picked from cros/chromeos-3.0 into the topic branches:\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\r\n\u003c/div\u003e\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003ccode\u003egit log \u003c/code\u003e\u003c/font\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003ccode\u003e--date\u003dshort --pretty\u003dformat:\"gp %h # %cd %s\"\u003c/code\u003e\u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003ccode\u003e \u003c/code\u003e\u003ci\u003e\u003ccode\u003elastsyncpoint\u003c/code\u003e\u003c/i\u003e\u003ccode\u003e..cros/chromeos-3.0 | \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003etac\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003c/div\u003e\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eRedirect output to a file or pipe into less if it's long.\u003c/font\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003e\r\nIn the order listed, copy and paste each line of the output into one \"corresponding\" topic branch window. The \"gp\" alias will cherry-pick that commit, and everything after the '#' will be ignored.   Merge conflicts may occur if \"gp\" was accidentally pasted in the wrong window OR the change doesn't belong in that topic branch. Either way, \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003euse git reset --hard \u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eto \"undo\" the failed cherry-pick in order to retry on a different topic branch.\u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/p\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e[\u003ci\u003eSome merge conflicts are likely to occur \r\nand require fix up if the original commit is based on a different \r\nrelease (e.g. v3.0.13) than the topic branch is based on (e.g. v.3.0). If topic branches were based on the same stable release (e.g. v3.0.13) at this point, such conflicts wouldn't occur.\u003c/i\u003e]\u003c/font\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-4:-sanity-check-Topic-Branches\" /\u003e\u003cfont size\u003d\"3\"\u003eStep 4: sanity-check Topic Branches\u003c/font\u003e\u003cbr /\u003e\r\n\u003c/h3\u003e\r\nHere's how to make sure the local topic branches contain all commits (assumes chromeos-3.0 is based on v3.0.13):\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:courier new,monospace;margin-left:40px\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit checkout -b mergetest v3.0.13\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit merge chromeos-base-3.0\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit merge chromeos-misc-3.0\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit merge chromeos-verity-3.0\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit merge chromeos-gobi-3.0\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit merge chromeos-tegra-3.0\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\nFix up (using $EDITOR), then \u003ccode\u003egit add\u003c/code\u003e and \u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit commit\u003c/code\u003e\u003c/span\u003e (to mergetest branch) conflicts between each merge.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n[Digression: Unfortunately, combining the topic branches into one merge command failed:\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003egit merge chromeos-{base,misc,verity,gobi,tegra}-3.0\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\nWe think this is either a git merge bug or the merge conflicts in our case prevented the octopus merge from running.]\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\nFinally, we get to verify with:\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit diff cros/chromeos-3.0\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\nThe diff should be empty. If it isn't, check first if one of the conflicts was resolved \"unfavorably\" and run \u003cspan style\u003d\"font-family:courier new,monospace\"\u003egit commit --amend\u003c/span\u003e to preserve the update. If not, something is missing from a topic branch. Hunt it down and add to the topic branch.\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-5:-Mark-sync-in-master-branch\" /\u003e\u003cfont size\u003d\"3\"\u003eStep 5: Mark sync in master branch\u003c/font\u003e\u003c/h3\u003e\r\n\u003c/div\u003e\r\nTo indicate in the master branch the points in time where \r\na topic branch sync occurred,  re-merge all the topic branches into the main \r\nbranch:\u003cbr /\u003e\r\n\u003cb style\u003d\"color:rgb(255,0,0)\"\u003e  TBD [ git commands to \"re-merge into main branch\" ]\u003c/b\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nSince the diff in Step 4 was empty, this results in an empty \r\nmerge changeset that will be used as a marker for the next time one has to \"resync\". This is the same \"mark\" (searching for \"Merge\") was used in Step 2.\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-6:-Create-new-Topic-Branches\" /\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eStep 6: Create new Topic-Branches\u003c/font\u003e\u003c/b\u003e\u003c/h3\u003e\r\n\u003cp\u003eThis is straight forward:\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003efor b in base misc gobi verity tegra ; do\u003c/code\u003e\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit checkout -b chromeos-${b}-3.2 chromeos-${b}-3.0\u003c/code\u003e\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003c/div\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003edone\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\nNo need to use the git-new-workdir.\r\n\u003cp\u003e\r\n\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-7:-Rebase--base-Topic-branch-first\" /\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eStep 7: Rebase -base Topic branch first\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/b\u003e\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003eRebase sounds simple. But it can get really really messy in some cases. Take it easy, be ready to throw away your work a couple of times and take plenty of notes. Do one branch at a time.\u003c/p\u003e\r\n\u003cp\u003eWe start with the -base branch since it contains the build infrastructure that's needed to build the kernel as an ebuild. This allows x86 builds/testing immediately. After \u003cfont face\u003d\"'courier new', monospace\"\u003echromeos-base-3.2\u003c/font\u003e is done, boot that on an x86 system to confirm. Then rebase each branch, one-by-one and rebuild the kernel after each branch is done.\u003c/p\u003e\r\n\u003cp\u003eSo, then in your main work dir:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit checkout chromeos-base-3.2\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit rebase v3.2 \u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003e\u003cbr /\u003e\r\ngit will stop on conflicts, you resolve them, \u003cspan style\u003d\"font-family:courier new,monospace\"\u003egit add\u003c/span\u003e (don't commit), and \u003cspan style\u003d\"font-family:courier new,monospace\"\u003egit rebase --continue\u003c/span\u003e. If conflicts get ugly, see \"Handling Rebase Conflicts\" advice below. When the rebase is done, do NOT commit until the result compiles. It's likely some kernel internal API changed and a merge was still referring to the old API. (e.g. v3.0 -\u0026gt; v3.2 had INIT_GROUP_RWSEM() change to INIT_THREADGROUP_FORK_LOCK()). One can compile with:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eFEATURES\u003d\"noclean\" emerge-$B chromeos-kernel\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eAnd once that compiles, try it. If the system boots, then run \u003cfont face\u003d\"'courier new', monospace\"\u003egit commit \u003c/font\u003efor each file that was modified. Later, when we run \"rebase -i\" below, we will re-order and \"squash\" or \"fixup\" each of those changes. Prefix each commit with something like \"REBASE_FIXUP\" so it's obvious which commits are fixups that need to be squashed.\u003c/p\u003e\r\n\u003cp\u003eMake sure to document changes made to resolve conflicts AND to fix compile failures in the commit message. This can be simple as appending a one-liner like this to the commit message:\u003c/p\u003e\r\n\u003cp\u003e\r\n\u003c/p\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003ccode\u003e[$WHOAMI: resolved trivial conflicts for 3.2] \u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003eSigned-off-by: Chromium KernDev \u0026lt;kerndev@chromium.org\u0026gt;\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eOnce kernel is booting with the given topic branch, run:\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit rebase -i v3.2\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eThe list of commits on the topic branch will be available to edit. See the comment at the bottom of that file to understand the options besides the default \"pick\".\u003c/p\u003e\r\n\u003cp\u003eAdditional Cleanups to do while running git rebase command above:\u003c/p\u003e\r\n\u003col\u003e\u003cli\u003e\u003cb\u003esquash chromeos/config commits\u003c/b\u003e: first just reorder commits together in \u003cfont face\u003d\"'courier new', monospace\"\u003egit rebase -i\u003c/font\u003e commit list, then mark those commits as \u003cfont face\u003d\"'courier new', monospace\"\u003efixup\u003c/font\u003e instead of \u003cfont face\u003d\"'courier new', monospace\"\u003epick\u003c/font\u003e.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eDrop reverted commits\u003c/b\u003e:  If a change is later on reverted, delete both the pick line for the original and revert commits.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eClean up Commit log entries\u003c/b\u003e: Someone missed the CHROMIUM: prefix? add it. Misformatted changelogs? Fix them up a bit. Etc.\u003c/li\u003e\r\n\u003c/ol\u003e\r\nRe-run the git rebase command as often as necessary to reduce the number of patches to a minimum. Add more topic branches if necessary.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Handling-Rebase-Conflicts\" /\u003eHandling Rebase Conflicts\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eAs shown above, on the first try, run \u003cfont face\u003d\"'courier new', monospace\"\u003egit rebase \u0026lt;newversion\u0026gt;\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e and see how ugly the conflicts get. Really lucky folks will get a few conflicts that can be resolved easily. The rest of us will find conflicting upstream changes.\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\r\n\u003cdiv\u003eIt's possible conflicts are due to a change appearing in multiple branches. Check and compare the contents of each topic branch with\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit log --oneline v3.2.. \u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\nDon't understand a conflict?  Backported commits get weird. First find the related commits using one or more of the following:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/font\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003egit log -S Sym v3.2 -- drivers/net/\u003cspan\u003e   \u003c/span\u003e# list commits touching \"Sym\" in v3.2 branch under drivers/net\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003egit diff HEAD -- drivers/net/r8169.c  # compare diff with current branch contents - NOT a 2-way diff\u003cbr /\u003e\r\n\u003c/font\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003egit log --stat\u003cspan\u003e\u003cspan\u003e chromeos-base-3.0 -- drivers/gpu/drm/\u003cspan\u003e  \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e# find \"big\" diffs in \u003c/code\u003e\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e\u003cspan\u003e\u003cspan\u003echromeos-base-3.0\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e and then look at them with \"git show\":\u003c/span\u003e\u003c/p\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003e\r\nFor the very bad cases, do the same as during the split-up into topic branches, run \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003ccode\u003egit log --oneline | tac | ...\u003c/code\u003e \u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e on the original branch and copy and paste each and every change over to have full control over what happens.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nIn some cases it's easier to apply the contents with:\u003cbr /\u003e\r\n\u003c/font\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cfont face\u003d\"'courier new', monospace\" style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit show \u0026lt;changeset\u0026gt; | patch -p1\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\" style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003e# fix up failed hunks\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003cfont face\u003d\"'courier new', monospace\" style\u003d\"font-family:courier new,monospace\"\u003e\u003ccode\u003egit commit -a -c \u0026lt;original changeset\u0026gt;\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThere are probably more clever ways of fixing up conflicts with git. But this method mostly works.\u003cbr /\u003e\r\n\u003c/font\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Debugging-Boot\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cb\u003eDebugging Boot\u003c/b\u003e\u003c/font\u003e\u003c/h4\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003eSince dm-verity isn't entirely upstream, first is to build and install an image with \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e--noenable_rootfs_verification\u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e. This will allow us to update the kernel for testing chromeos-base-3.2:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e./build_image --board\u003d$B --test --noenable_rootfs_verification\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cfont face\u003d\"arial, sans-serif\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\nOnce we merge in chromes-verity-v3.2 topic branch, then we can rebuild normally.\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\r\nThen get the kernel to spew it's verbage to the console. Here's the list the parameters to modify:\u003cbr /\u003e\r\n\u003c/font\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003equiet\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e : delete this one\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eloglevel\u003d1\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e : replace with \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eloglevel\u003d7\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e or \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003edebug\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003econsole\u003dtty2\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e : replace with \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003econsole\u003dtty1.\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eAlso add \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003econsole\u003dttyS0\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e if serial console is available (\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eservo\u003c/a\u003e or mini-PCIe serial card)\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eOne can modify the parameters in two places depending on which tools are used to push kernels:\u003cbr /\u003e\r\n\u003c/font\u003e\r\n\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eupdate_kernel.sh : vi ~/trunk/src/build/images/$B/latest/config.txt\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ebuild_image.sh : vi ~/trunk/src/scripts/build_kernel_image.sh\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e and modify where this script writes out parameters to config.txt. Then (re)run build_image as shown above.\u003c/font\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-8:-Push--base-Topic-Branch\" /\u003eStep 8: Push -base Topic Branch\u003c/h3\u003e\r\n\u003cp\u003e\u003ci\u003e\u003cb\u003eBefore pushing your branch, contact \u003c/b\u003e\u003c/i\u003e\u003cb\u003e\u003ci\u003e\u003ca href\u003d\"https://groups.google.com/a/chromium.org/group/chromium-os-dev\" target\u003d\"_blank\"\u003eChromium OS dev\u003c/a\u003e\u003c/i\u003e\u003c/b\u003e\u003ci\u003e\u003cb\u003e mailing list to request a push of a kernel.org/linus tag (e.g. v3.2) to kernel-next and kernel repos AND permissions to push a new branch to kernel-next and kernel repos. Please include a reference to this page so people understand what you are asking for.\u003c/b\u003e\u003c/i\u003e\u003c/p\u003e\r\n\u003cp\u003eSetup and push to chromium.org repo commands:\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit remote add kernel-ssh https://chromium.googlesource.com/chromiumos/third_party/kernel.git\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit remote add kernel-next-ssh https://chromium.googlesource.com/chromiumos/third_party/kernel-next.git\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit push kernel-next-ssh chromeos-base-3.2\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003eIf the chromeos-base-X.Y branch needs another rebase or drop some commits/whatever, push the branch again. If you haven't yet, also push the previous release branches (can be one command if preferred) that have been sync'd:\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit push kernel-next-ssh chromeos-gobi-3.0 \u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit push kernel-next-ssh chromeos-misc-3.0 \u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit push kernel-next-ssh chromeos-verity-3.0 \u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit push kernel-next-ssh chromeos-tegra-3.0\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-9:-Rebase-other-Topic-branches\" /\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003eStep 9: Rebase other Topic branches\u003c/font\u003e\u003c/h3\u003e\r\n\u003cp\u003eTopic branches other than -base, depend on -base. So we need to do the rebase slightly differently. -misc topic branch is used in the examples below but the process should be the same for any topic branch. Instructions here are essentially the same as \"\u003cb\u003e\u003ci\u003eRebase -base Topic branch first\u003c/i\u003e\u003c/b\u003e\" step.\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit checkout chromeos-misc-3.2\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit rebase v3.2\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nFix up merge conflicts. Commit each file touched separately. Don't build (yet). Then squash fixups/cleanup into original commits with:\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit rebase -i v3.2\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nNow build/test/ using a \"junk branch\" to park commits on:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit checkout -b mergetest chromeos-base-3.2\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit merge chromeos-misc-3.2\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eDo the previously described build/boot/fixup/commit cycle until things look good (enough). Then we need to bring those changes back into the original topic branch we are working.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit checkout chromeos-misc-3.2\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit log mergetest    # in one window\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit cherry-pick \u0026lt;mergetest commits\u0026gt; # in another window\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eAt this point. it's possible conflicts are due to a change appearing in multiple branchs. When working on a topic branch (checked out), check/record the contents of that topic branch with:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit log --oneline v3.2.. \u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eAnd as usual, squash, drop, or fix up and commit cleanups with \"-i\" parameter:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003egit rebase -i v3.2\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eWhen done, tree builds and boots on a machine, then push the tree to kernel-next (or kernel) with:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003ccode\u003egit push kernel-next-ssh chromeos-misc-3.2\u003c/code\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-10:-Merge-Topic-Branches\" /\u003e\u003cb style\u003d\"font-family:arial,sans-serif;font-size:medium\"\u003eStep 10: Merge Topic Branches\u003c/b\u003e\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eMerge all the branches together (like you did at the end of the topic branch splitup), then try compiling and see how much is broken. e.g.:\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003ccode\u003egit checkout -b chromeos-3.2 chromeos-base-3.2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003ccode\u003egit merge \u003c/code\u003e\u003ccode\u003echromeos-misc-3.2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003ccode\u003egit merge chromeos-gobi-3.2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003ccode\u003egit merge chromeos-verity-3.2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003ccode\u003egit merge chromeos-input-3.2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\nExpect to fix ups conflicts/mistakes in earlier steps:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003col\u003e\u003cli\u003ecommit each fixed file into the merged-together branch with \"FIXUP\" prefix (so they are easy to find later).\u003c/li\u003e\r\n\u003cli\u003efind the topic branch which has the conflicting change:\u003cbr /\u003e\r\n\u003ccode\u003egit log -S \u0026lt;symbol\u0026gt; -- \u0026lt;filename\u0026gt; # find candidate commits which touch \u0026lt;symbol\u0026gt;\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003egit show \u0026lt;SHA1\u0026gt; # confirm this is the conflict\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003eCheckout the topic branch with the offending \u0026lt;SHA1\u0026gt;.\u003c/li\u003e\r\n\u003cli\u003echerry pick the FIXUP \u0026lt;SHA1\u0026gt; into that topic branch.\u003c/li\u003e\r\n\u003cli\u003egit rebase -i v3.2 and squash the FIXUP into the commit that introduced the problem.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\r\n\u003cdiv\u003eThe result is less noise in the change log, a cleaner history, and the branch will be more bisectable. \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThen delete (or reset to pre-merge state) the \"merge branch\" (chromeos-3.2 in above example) and redo the merge from scratch. If you move the old branch aside, you can diff the two end results and make sure they are the same.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-11:-Test-Merged-Branch\" /\u003eStep 11: Test Merged Branch\u003c/h3\u003e\r\n\u003cdiv\u003eThe very first testing is to see if the system even comes up. It is easier to work with just one system on your desk. Once that comes up, suspend-resumes and reboots cleanly, I kick off a handful of labtest runs of bvt and regression.\u003c/div\u003e\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-12:-Change-the-manifests-for-kernel-next.git-and-ask-for-help\" /\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003eStep 12: Change the manifests for kernel-next.git and ask for help\u003c/font\u003e\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eSend out a PSA saying \"switching kernel-next over to track chromeos-X.Y\" on chromium-os-dev, and change the internal and external manifests to track the new branch by default. I normally do this before I ask others to start pitching in on testing since it makes it easier to make sure you're tracking the right sources.\u003c/font\u003e\u003c/div\u003e\r\n\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eAlso, this is the time when I start asking various subteams and other team members to start pitching in and testing the new kernel on whatever hardware they have. For 3.0, I created a large number of bugs in the bugtracker for sign-off, which worked quite well. I made those bugs blockers of the root \"rebase to 3.0\" bug.\u003c/font\u003e\u003c/p\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003ecd ~/trunk/.repo\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit branch   # see which branches are available\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit checkout default\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit pull\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit branch update-kernelnext\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e$EDITOR oldlayout.xml  # update kernel-next version\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit diff # review change\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit commit  # \"kernel-next: move to chromeos-3.2 branch\"\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit push origin HEAD:refs/for/master\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/font\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Step-13:-Move-over-to-kernel.git-and-change-those-manifests\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eStep 13: Move over to kernel.git and change those manifests\u003c/font\u003e\u003c/h3\u003e\r\n\u003cp\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eOnce testing in kernel-next.git look reasonably stable, the branches are clean (don't contain too much cruft), the time has come to move the branches back to the kernel.git repo. Use \"\u003cspan style\u003d\"font-family:courier new,monospace\"\u003egit push\u003c/span\u003e\" to the kernel.git repo (appropriate permissions needed in gerrit):\u003c/font\u003e\u003c/p\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egit push kernel-ssh chromeos-3.2\u003c/code\u003e\u003c/div\u003e\u003c/font\u003e\u003c/div\u003e\u003cp\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eWhen the pushed branch looks good, update the manifest to point to the new branch just like for kernel-next. Send PSAs  to chromium-os-dev when before, during, and after changing the manifest:\u003c/span\u003e\u003c/p\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003ecd ~/trunk/.repo/manifests/\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e# updating public manifest requires SSH access\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit remote add manifest-ssh https://chromium.googlesource.com/chromiumos/manifest.git\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit remote update\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit branch -a  # see which branches are available\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit checkout remotes/manifest-ssh/master\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit branch update-kernel\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit checkout update-kernel\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e$EDITOR oldlayout.xml  # update kernel version\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit diff # review change\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit commit  # \"kernel: move to chromeos-3.2 branch\"\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003egit push manifest-ssh HEAD:refs/for/master\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e# internal manifest update: git push origin HEAD:refs/for/m\u003c/code\u003e\u003ccode\u003easter\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv\u003eThe above will create a gerrit change that needs to be reviewed/approved.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e(\u003ci\u003eReminder: ChromeOS folks will also need to update manifest-internal\u003c/i\u003e)\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Step-14:-Wait-and-debug\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eStep 14: Wait and debug\u003c/font\u003e\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eOnce the new kernel tree is in production, you will surely start hearing about problems. Have fun! :) Usually it's a smaller number of problems. If things look really bad, the manifest can always be switched back to the old branch.\u003c/font\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Important-notes\" /\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"5\"\u003e\u003cb\u003eImportant notes\u003c/b\u003e\u003c/font\u003e\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb style\u003d\"font-family:arial,sans-serif\"\u003eDOCUMENT YOUR WORK! \u003c/b\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThis is extremely important. If you have to touch up a commit, document it! The way to do it is in the commit message, adding your own Signed-off-by with a quick one-line comment above. For example:\u003cbr /\u003e\r\n\u003cspan style\u003d\"background-color:rgb(239,239,239)\"\u003e\u003cbr /\u003e\r\n\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"line-height:13px\"\u003ecommit 462fd39525eb3221d320ff3f0eaaddec1ed28a80\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003eAuthor: Yen Lin \u0026lt;yelin@nvidia.com\u0026gt;\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003eDate:   Thu Aug 18 10:14:03 2011 -0700\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    CHROMIUM: arm: tegra: reserve lp0_vec, fb and carveout\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    \u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    The fb, fb2 and carveout memory reserved are from high address memory.\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    That means with the current u-boot \"mem\u003d384M@0M nvmem\u003d128M@384M mem\u003d512M@512M\"\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    cmdline parameter, there will be a 128MB hole wasted.\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    \u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    BUG\u003dchrome-os-partner:5501\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    TEST\u003dhot-plug HDMI then perform suspend/resume LP0\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    \u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    Change-Id: I1e8877623e62afa7f1a3ad0dd6938e83db5bd188\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    Signed-off-by: Yen Lin \u0026lt;yelin@nvidia.com\u0026gt;\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    Reviewed-on: http://gerrit.chromium.org/gerrit/6290\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    Reviewed-by: Bryan Freed \u0026lt;bfreed@chromium.org\u0026gt;\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    Tested-by: Bryan Freed \u0026lt;bfreed@chromium.org\u0026gt;\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    [olofj: split up in common.c change and board change, and cleanup]\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:arial,sans-serif;line-height:13px;text-align:left;background-color:rgb(239,239,239)\"\u003e\u003ccode\u003e    Signed-off-by: Olof Johansson \u0026lt;olofj@chromium.org\u0026gt;\u003c/code\u003e\u003c/div\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cul\u003e\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eLikewise, just keep a short log of the patches that you drop due to conflicts at rebase, so you can come back and revisit them when the branch is done.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eKeep track of which patches didn't apply, so you can tell people what work needs to be done. For example, I have traditionally not made much of an effort to bring wifi patches forward, since I know most of them are backports and Sam and Paul have been doing a good job of re-syncing it (they are the ones who know how to run the tests, and more importantly, parse the test results, in the first place). But keep a log of it, so you know who to ask for help later on.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eDuring split-up, you might realize that someone has done a change that touches several topic branches. In most cases, this is a time when it makes sense to split up the commit into several ones. Typical case is when someone did a config change as part of a code change, or someone changed both ARM board code and a driver as one change. Split the commit and fixup the commit message as appropriate here. Use your judgement and taste for what is reasonable to do.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eCompile often during rebase to catch build errors as soon as they are introduced as possible. If you miss them, then fix them up, commit into a separate change, and then go back and squash that change in with the offending commit (documenting the fixup in the Signed-off-by trail just like with other edits).\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eOnce you move the code over to kernel.git, make sure noone is commiting to kernel-next.git. This causes pain if you want to keep the two trees in sync since things will merge in different order instead of just fast-forward when you merge over, and overall it can cause confusion.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eI normally tell people that I will try to keep the new kernel.git checkins in sync with kernel-next.git (i.e. bring them over) once the rebase starts. In some cases people have still been submitting their code to both trees, which is OK but be careful that you do bring everything over since it can be easy to miss things when some is in already and some is not.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"text-align:left\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eDo the rebase of the topic branches on top of the master mainline release (i.e. 3.0), but merge them together on top of the latest -stable at the time (3.0.8). This way next rebase will be easier. Make sure to split up into topic branches before you merge in a new stable release into kernel.git ToT as well (i.e. if you want to update that tree to 3.0.10).\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/kernel-rebase-notes"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4013088826456316651"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4013088826456316651"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4013088826456316651"}],"author":[{"name":{"$t":"Olof Johansson"},"email":{"$t":"olofj@chromium.org"}}],"sites$pageName":{"$t":"kernel-rebase-notes"},"sites$revision":{"$t":"54"}},{"gd$etag":"\"Xyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3207933497028372659"},"published":{"$t":"2011-03-16T19:13:09.649Z"},"updated":{"$t":"2015-05-19T20:03:05.494Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-19T20:03:03.987Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Anti-DDoS HTTP Throttling of Extension-Originated Requests"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eChrome 20 and later implements a mechanism that is intended to prevent distributed denial of service (DDoS) attacks from being perpetrated, maliciously or accidentally, by extensions running within Chrome. Chrome 12 through 19 had a different flavor of this feature, see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/throttling/anti-ddos-http-throttling-in-older-versions-of-chrome\"\u003ehere\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo disable the feature, which may be useful for some extension developers:  Pass the \u003cb\u003e--disable-extensions-http-throttling\u003c/b\u003e command-line flag when starting Chrome.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe way the mechanism works is, once a few server errors (HTTP error codes 500 and greater) in a row have been detected for a given URL (minus the query parameters), Chrome assumes the server is either unavailable or overloaded due to a DDoS, and denies requests to the same URL for a short period of time. If, after this period of time, requests keep failing, this \"back-off interval\" period is increased using an exponential factor, and so on and so forth until the maximum back-off interval is reached. It's important to note that failures due to the throttling itself are not counted as failures that cause the back-off interval to be increased.\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe back-off delay is calculated as follows:  delay \u003d initial_backoff * multiply_factor^(effective_failure_count - 1) * Uniform(1 - jitter_factor, 1]\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor the canonical details on the back-off parameters used, see \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/net/url_request/url_request_throttler_entry.cc?view\u003dmarkup\"\u003ehttp://src.chromium.org/viewvc/chrome/trunk/src/net/url_request/url_request_throttler_entry.cc?view\u003dmarkup\u003c/a\u003e. What follows is based on the most recent values for these parameters as of this writing:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe back-off parameters used in the formula above will (at maximum values, i.e. without the reduction caused by jitter) add 0-41% (distributed uniformly in that range) to the \"perceived downtime\" of the remote server, once exponential back-off kicks in and is throttling requests for more than about a second at a time. Once the maximum back-off is reached, the added perceived downtime decreases rapidly, percentage-wise. \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAnother way to put it is that the maximum additional perceived downtime with these numbers is a couple of seconds shy of 15 minutes, and such a delay would not occur until the remote server has been actually  unavailable at the end of each back-off period for a total of about 48 minutes.\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eBack-off does not kick in until after the first 4 errors, which helps avoid back-off from kicking in on// flaky connections. To simplify life for web developers, throttling is never used for URLs that resolve to localhost.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you believe your extension may be having problems due to HTTP throttling, you can try the following:\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003ePass the \u003cb\u003e--disable-extensions-http-throttling\u003c/b\u003e command-line flag when starting Chrome, to see if the problem reproduces with the feature turned off.\u003c/li\u003e\u003cli\u003eWith exponential back-off throttling of extension requests turned on (i.e. \u003cb\u003ewithout\u003c/b\u003e the command-line flag above), visit \u003ca href\u003d\"javascript:void(0);\"\u003echrome://net-internals/#events\u003c/a\u003e and keep it open while you reproduce the problem you were seeing. Diagnostic information will be added to the log, which may help you track down what is happening.\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/throttling"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3207933497028372659"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3207933497028372659"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3207933497028372659"}],"author":[{"name":{"$t":"Jói Sigurðsson"},"email":{"$t":"joi@chromium.org"}}],"sites$pageName":{"$t":"throttling"},"sites$revision":{"$t":"16"}},{"gd$etag":"\"WSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2435127149714323596"},"published":{"$t":"2014-05-09T18:05:51.452Z"},"updated":{"$t":"2015-05-18T14:25:27.709Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-18T14:25:26.275Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Asus Chromebox"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eEntering\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-USB-Boot\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eUSB Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eLegacy Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eLeaving\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Troubleshooting\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eTroubleshooting\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot-Doesn-t-Work\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eLegacy Boot Doesn't Work\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Running-Chromium-OS\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eRunning Chromium OS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the Asus Chromebox that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003eCPU: Haswell Celeron 2995U. 1.4GHz, dual-core, 2MB Cache OR\u003cfont size\u003d\"2\"\u003e \u003cspan style\u003d\"font-family:Arial;line-height:18px\"\u003e1.7 GHz Core i3-4010U, quad-core\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GB (celeron) or 4GB (i3)\u003c/li\u003e\r\n\u003cli\u003eDisplay: \u003cspan style\u003d\"background-color:transparent\"\u003eNone\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eDisk: 16GB SSD (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Next_Generation_Form_Factor\" rel\u003d\"nofollow\"\u003eNGFF\u003c/a\u003e M.2 connector)\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eI/O:\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI port\u003c/li\u003e\r\n\u003cli\u003eDisplayPort++\u003c/li\u003e\r\n\u003cli\u003e4 x USB 3.0\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eUSB ports can handle some Ethernet dongles\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eEthernet\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eServo header\u003c/a\u003e: Standard 2x25 / AXK750347G\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eIntroduction\u003c/font\u003e\u003c/b\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003cp\u003eEnabling Developer mode is the first step to tinkering with your Chromebox. With Developer mode enabled you can do things like poke around on a command shell (as root if you want), install Chromium OS, or try other OS's. Note that Developer mode turns off some security features like verified boot and disabling the shell access. If you want to browse in a safer, more secure way, leave Developer mode turned OFF. Note: Switching between Developer and Normal (non-developer) modes will remove user accounts and their associated information from your Chromebox.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Entering\" /\u003eEntering\u003c/h3\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eTo invoke Recovery mode, you insert a paper clip and press the \u003cfont color\u003d\"#990000\"\u003eRECOVERY\u003c/font\u003e\u003cfont color\u003d\"#e06666\"\u003e \u003c/font\u003e\u003cfont color\u003d\"#990000\"\u003eBUTTON \u003c/font\u003e(just above the kensington lock) and\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e press the\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003cfont color\u003d\"#990000\" style\u003d\"background-color:transparent;font-size:10pt\"\u003ePower\u003c/font\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ebutton. Release the \u003cfont color\u003d\"#990000\"\u003eRECOVERY BUTTON\u003c/font\u003e after a second.\u003c/span\u003e\u003c/p\u003e\r\n\u003cp\u003eTo enter Dev-mode you first invoke Recovery, and at the Recovery screen press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e (there's no prompt - you have to know to do it). It will ask you to confirm by pressing the \u003cfont color\u003d\"#990000\"\u003eRECOVERY BUTTON\u003c/font\u003e again.\u003c/p\u003e\r\n\u003cp\u003eDev-mode works the same as always: It will show the scary boot screen and you need to press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e or wait 30 seconds to continue booting.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-USB-Boot\" /\u003eUSB Boot\u003c/h3\u003e\r\n\u003cp\u003eBy default, USB booting is disabled. Once you are in Dev-mode and have a root shell (Ctrl-Alt-F2), you can run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo crossystem dev_boot_usb\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot from USB drives with Ctrl-U.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot\" /\u003eLegacy Boot\u003c/h3\u003e\r\n\u003cp\u003eThis device includes the SeaBIOS firmware which supports booting images directly like a legacy BIOS would. Note: the BIOS does not provide a fancy GUI for you, nor is it easy to use for beginners. You will need to manually boot/install your alternative system.\u003c/p\u003e\r\n\u003cp\u003eLike USB boot, support for this is disabled by default. You need to get into Dev-mode first and then run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo crossystem dev_boot_legacy\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot legacy images with \u003cfont color\u003d\"#990000\"\u003eCtrl-L.\u003c/font\u003e\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Leaving\" /\u003eLeaving\u003c/h3\u003e\r\n\u003cp\u003eTo leave Dev-mode and go back to normal mode, just follow the instructions at the scary boot screen. It will prompt you to confirm.\u003c/p\u003e\r\n\u003cp\u003eIf you want to leave Dev-mode programmatically, you can run \u003ccode\u003ecrossystem disable_dev_request\u003d1; reboot\u003c/code\u003e from a root shell. There's no way to enter Dev-mode programmatically, and just seeing the Recovery screen isn't enough - you have to use the three-finger salute which hard-resets the machine first. That's to prevent a remote attacker from tricking your machine into dev-mode without your knowledge.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Troubleshooting\" /\u003eTroubleshooting\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot-Doesn-t-Work\" /\u003eLegacy Boot Doesn't Work\u003c/h3\u003e\r\n\u003cp\u003eSometimes it's possible to break the SeaBIOS install in the flash (sometimes doing innocuous things like tweaking the GBB flags). If you do get into such a situation:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eCheck that dev_boot_legacy is set to 1 when you run crossystem\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIf it isn't, then see the normal Legacy Boot section above\u003c/li\u003e\r\n\u003cli\u003eif it is, then see below\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cp\u003eYou can safely reset the copy of SeaBIOS in your flash by running (as root):\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e# chromeos-firmwareupdate --sb_extract /tmp\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e# flashrom -w /tmp/bios.bin -i RW_LEGACY\u003c/code\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Running-Chromium-OS\" /\u003eRunning Chromium OS\u003c/h2\u003e\r\n\u003cp\u003eBefore you start fiddling with your own builds it is strongly recommend to create a recovery USB stick or SD card. As long as you don't disable hardware write protect on the system \u0026amp; EC firmware, you can get your machine back into working order by entering Recovery Mode and plugging in your recovery image. You can create a recovery image from Chrome OS by browsing to \u003ca style\u003d\"color:rgb(71,18,100)\"\u003echrome://imageburner\u003c/a\u003e or follow instructions for other OS on the \u003ca href\u003d\"https://support.google.com/chromebook/answer/1080595?hl\u003den\"\u003eChrome OS help center\u003c/a\u003e site.\u003c/p\u003e\r\n\u003cp\u003eYou can build and run Chromium OS on your Asus Chromebox (versions R32 and later). Follow the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/quick-start-guide\"\u003equick start guide\u003c/a\u003e to setup a build environment. The board name for the Asus Chromebox is \"panther\". Build an image and write it to a USB stick or SD card.\u003c/p\u003e\r\n\u003cp\u003eTo boot your image you will first need to enable booting developer signed images from USB (or SD card). Switch your machine to Developer mode and get to a shell by either via VT2 (Ctrl+Alt+F2) and logging in as root or by logging in as a user (or guest mode), starting a \"crosh\" shell with Ctrl+Alt+t, and typing \"shell\". Now run \"sudo crossystem dev_boot_usb\u003d1\" and reboot \"sudo reboot\".\u003c/p\u003e\r\n\u003cp\u003ePlug your USB stick or SD card in and on the scary \"OS Verification is OFF\" screen hit Ctrl+u to boot from external media. If all goes well you should see a \"Chromium OS\" logo screen. If you want to install your build to the SSD, open a shell and type \"sudo /usr/sbin/chromeos-install\". Note: This will replace EVERYTHING on your SSD. Use a recovery image if you want to get back to a stock Chrome OS build.\u003c/p\u003e\r\n\u003cp\u003eHave fun!\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-panther-4920.24.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-panther-4920.24.B\u003c/code\u003e branches.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/asus-chromebox"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2435127149714323596"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2435127149714323596"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2435127149714323596"}],"author":[{"name":{"$t":"Mohammed Habibulla"},"email":{"$t":"moch@chromium.org"}}],"sites$pageName":{"$t":"asus-chromebox"},"sites$revision":{"$t":"10"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6102096911475364262"},"published":{"$t":"2011-01-20T19:48:42.727Z"},"updated":{"$t":"2015-05-14T02:26:20.452Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2011-12-20T00:13:46.819Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Language Detection for chunks of text"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-OverviewAdd-a-new-chrome.i18n.detectLanguage-that-enables-CLD-language-detection-for-a-chunk-of-user-supplied-text.Use-casesThis-API-would-be-useful-for-extensions-that-want-to-translate-parts-of-a-page-that-are-in-a-different-language-than-the-page-itself\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;font-weight:normal\"\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eOverview\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eAdd a new \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003echrome.i18n.detectLanguage\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e that enables CLD language detection for a chunk of user-supplied text.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eUse cases\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThis API would be useful for extensions that want to translate parts of a page that are in a different language than the page itself. This is also useful in implementing an extension that translates user-supplied text (in a gadget, for example) into a language of the user’s choice, without needing to rely on an external server for language detection of the text. The existing \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003echrome.tabs.detectLanguage\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e API only provides language detection on a page-level granularity.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eCould this API be part of the web platform?\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eNo, this is intended to fill in a functionality gap with an existing chrome extension API, and not to introduce new web standards.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eDo you expect this API to be fairly stable?\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThe set of languages that can be detected by the CLD may change over time, which affects the results of this function in a similar way as \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003echrome.tabs.detectLanguage\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eWhat UI does this API expose?\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eNone.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eHow could this API be abused?\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThere’s nothing obvious that could be abused here.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eHow would you implement your desired features if this API didn't exist?\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThe only way to detect the language of a chunk of text from a page right now would be to transmit the text to a third party server and wait for a reply. This is not desirable as it introduces privacy concerns about sending text scraped from parts of a page to a server before a user explicitly requests they be translated.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eAre you willing and able to develop and maintain this API?\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eYes.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:18pt;direction:ltr;padding-bottom:4pt;font-size:18pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eDraft API spec\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:14pt;text-indent:0pt;padding-bottom:4pt;direction:ltr;font-size:14pt;font-weight:bold\"\u003e\u003cspan\u003eMethods\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003edetectLanguage\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003echrome.i18n.detectLanguage(string \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt;font-style:italic\"\u003etext\u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003e, function \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt;font-style:italic\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003e)\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eDetects the primary language of a supplied chunk of text. Language detection is more reliable for larger chunks of text (preferably 100 characters or more), but may be able to make a determination with small chunks for languages that use unique characters, such as Arabic or Hebrew.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eParameters\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-style:italic;font-family:Verdana\"\u003etext ( string )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:80pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThe text to analyze.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-style:italic;font-family:Verdana\"\u003ecallback ( function )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:80pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-style:italic;font-family:Verdana\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e parameter should specify a function that looks like this:\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:80pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003efunction(array of DetectedLanguage languages) {...};\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:80pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-style:italic;font-family:Verdana\"\u003eresult \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0);font-style:italic;font-size:10pt;font-weight:bold;font-family:Verdana\"\u003e( \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-style:italic;font-family:Verdana\"\u003eLanguageDetectionResult \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0);font-style:italic;font-size:10pt;font-weight:bold;font-family:Verdana\"\u003e)\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:108pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eWill contain up to three languages that were detected in \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-style:italic;font-family:Verdana\"\u003etext\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:120pt;padding-top:12pt;padding-bottom:2pt;text-indent:0pt;direction:ltr;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e \u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:36pt;padding-top:12pt;padding-bottom:2pt;text-indent:0pt;direction:ltr;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:14pt\"\u003eTypes\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:36pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-family:Verdana\"\u003eDetectedLanguage\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:36pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003e( object )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:36pt;text-indent:36pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003elanguage ( string )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:108pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eAn ISO language code such as \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003een\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e or \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003efr\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e. For a complete list of languages that could be returned here, see \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,204);text-decoration:underline;font-size:10pt;font-family:Verdana\"\u003e\u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/third_party/cld/languages/internal/languages.cc\"\u003ekLanguageInfoTable\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e. The 2nd to 4th columns will be checked and the first non-NULL value will be returned except for Simplified Chinese for which \u003c/span\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:Courier New;font-size:10pt\"\u003ezh-CN\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e will be returned.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;direction:ltr\"\u003e\u003cspan style\u003d\"font-family:Verdana\"\u003e                \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003econfidence ( integer )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:108pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eA value between 0 and 100, inclusive, that indicates Chrome’s percentage confidence that the supplied text is in this language. High values indicate high confidence.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:36pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-family:Verdana\"\u003e \u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:40pt;padding-top:12pt;text-indent:0pt;direction:ltr;padding-bottom:2pt;font-size:12pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eLanguageDetectionResult\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:1.15;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-style:italic;font-family:Verdana\"\u003e        \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003e( Object)\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:72pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003ereliable ( boolean )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:108pt;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eTrue if language detection was considered reliable. This is the case when a single language emerges with a confidence value that is significantly higher than the next most likely language.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003e                \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003elanguages ( array of DetectedLanguage )\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:1.15;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:bold;font-style:italic;font-family:Verdana\"\u003e                        \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eThe possible languages that were detected for the supplied text, if any.\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:108pt;text-indent:0pt;direction:ltr;line-height:1.15\"\u003e\u003cspan style\u003d\"font-family:Verdana\"\u003e \u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:14pt;text-indent:0pt;padding-bottom:4pt;direction:ltr;font-size:14pt;font-weight:bold\"\u003e\u003cspan style\u003d\"font-size:13pt\"\u003eOpen questions\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:1.15;text-indent:0pt;direction:ltr\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Verdana\"\u003eIs it useful to return the raw confidence numbers for each language? These may change with each new implementation of the CLD.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/h2\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/333592083211368911"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/proposed-changes/apis-under-development/language-detection"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6102096911475364262"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6102096911475364262"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6102096911475364262"}],"author":[{"name":{"$t":"Marc-André Decoste"},"email":{"$t":"mad@chromium.org"}}],"sites$pageName":{"$t":"language-detection"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"Wyl7JmA_\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2506161099712800377"},"published":{"$t":"2014-02-11T23:50:29.858Z"},"updated":{"$t":"2015-05-13T16:51:08.702Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-13T16:51:07.566Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chrome Extension Developer FAQ for upcoming changes in May 2015 related to hosting extensions"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cfont size\u003d\"3\"\u003eAs a follow-up to our blog post on \u003c/font\u003e\u003cspan\u003e\u003ca href\u003d\"http://blog.chromium.org/2015/05/continuing-to-protect-chrome-users-from.html\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"3\"\u003econtinuing to protect Chrome users from malicious extensions\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003cfont size\u003d\"3\"\u003e, we’re enforcing the following changes starting in May 2015 for all Windows channels and starting in July 2015 for all Mac channels:\u003cbr /\u003e\u003c/font\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eUsers can only install extensions hosted in the Chrome Web store, except for installs via \u003c/span\u003e\u003ca href\u003d\"https://support.google.com/chrome/a/answer/188453\" style\u003d\"background-color:transparent\"\u003eenterprise policy\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e or \u003c/span\u003e\u003ca href\u003d\"http://developer.chrome.com/extensions/getstarted.html#unpacked\" style\u003d\"background-color:transparent\"\u003edeveloper mode\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eExtensions that were previously installed, but not hosted on the Chrome Web Store will be \u003c/span\u003e\u003ca href\u003d\"https://support.google.com/chrome/answer/2811969\" style\u003d\"background-color:transparent\"\u003ehard-disabled\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e (i.e. the user cannot enable these extensions again), except for installs via \u003c/span\u003e\u003ca href\u003d\"https://support.google.com/chrome/a/answer/188453\" style\u003d\"background-color:transparent\"\u003eenterprise policy\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e or \u003c/span\u003e\u003ca href\u003d\"http://developer.chrome.com/extensions/getstarted.html#unpacked\" style\u003d\"background-color:transparent\"\u003edeveloper mode\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-the-rationale-for-this-measure-\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eWhat’s the rationale for this measure?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-For-extensions-that-are-currently-hosted-outside-the-Chrome-Web-Store-what-should-be-done-and-by-when-\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eFor extensions that are currently hosted outside the Chrome Web Store, what should be done and by when?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-will-happen-if-I-migrate-the-extension-to-the-Chrome-Web-Store-sometime-in-the-future-Will-I-lose-all-my-users-\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eWhat will happen if I migrate the extension to the Chrome Web Store sometime in the future? Will I lose all my users?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-if-I-want-to-restrict-access-to-certain-users-or-prevent-my-extension-from-being-listed-on-the-Chrome-Web-Store-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat if I want to restrict access to certain users or prevent my extension from being listed on the Chrome Web Store?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Which-operating-systems-and-Chrome-channels-are-affected-by-this-change-\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eWhich operating systems and Chrome channels are affected by this change?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Will-this-affect-my-ability-to-develop-my-extensions-on-Windows-\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eWill this affect my ability to develop my extensions on Windows?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Why-couldn-t-this-problem-be-solved-by-having-a-setting-option-to-load-extensions-that-are-not-hosted-in-the-Chrome-Web-Store-\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eWhy couldn't this problem be solved by having a setting/option to load extensions that are not hosted in the Chrome Web Store?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-are-the-supported-deployment-options-for-extensions-after-this-change-\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eWhat are the supported deployment options for extensions after this change?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Are-there-any-other-considerations-to-be-aware-of-for-extensions-that-depend-on-a-native-application-binary-\"\u003e\u003cstrong\u003e9 \u003c/strong\u003eAre there any other considerations to be aware of for extensions that depend on a native application binary?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-will-users-see-when-their-off-store-extension-is-disabled-as-a-result-of-this-rollout-\"\u003e\u003cstrong\u003e10 \u003c/strong\u003eWhat will users see when their off-store extension is disabled as a result of this rollout?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Why-do-I-see-a-bubble-about-Disable-developer-mode-extensions-when-loading-an-unpacked-extension-in-Windows-stable-beta-channels-\"\u003e\u003cstrong\u003e11 \u003c/strong\u003eWhy do I see a bubble about “Disable developer mode extensions” when loading an unpacked extension in Windows stable/beta channels?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-the-rationale-for-this-measure-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eWhat’s the rationale for this measure?\u003c/b\u003e\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:medium;background-color:transparent;font-weight:normal\"\u003eSee \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003e\u003cspan style\u003d\"text-decoration:underline;font-family:Arial;color:rgb(17,85,204);vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"http://blog.chromium.org/2015/05/continuing-to-protect-chrome-users-from.html\" style\u003d\"text-decoration:none\"\u003eContinuing to protect Chrome users from malicious extensions\u003c/a\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:medium;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-For-extensions-that-are-currently-hosted-outside-the-Chrome-Web-Store-what-should-be-done-and-by-when-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eFor extensions that are currently hosted outside the Chrome Web Store, what should be done and by when?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eIf your extensions are currently hosted outside the Chrome Web Store you should migrate them to the Chrome Web Store as soon as possible. The above changes will very soon become effective for all channels on Windows and will become effective for all Mac channels in July 2015. Once you migrate your extensions to the Chrome Web Store, there will be no impact to your users, who will still be able to use your extension as if nothing changed. And if you have a dedicated installation flow from your own website, you can make use of the existing \u003ca href\u003d\"https://developers.google.com/chrome/web-store/docs/inline_installation\"\u003einline installs\u003c/a\u003e feature.\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-will-happen-if-I-migrate-the-extension-to-the-Chrome-Web-Store-sometime-in-the-future-Will-I-lose-all-my-users-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhat will happen if I migrate the extension to the Chrome Web Store sometime in the future? Will I lose all my users?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eUsers will have their off-store extensions hard-disabled once the enforcement rolls out. However, if the extension is migrated to the Chrome Web Store after the rollout, users will be able to manually enable the migrated extension from extensions settings page (chrome://extensions) or from the Chrome Web Store listing.\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-if-I-want-to-restrict-access-to-certain-users-or-prevent-my-extension-from-being-listed-on-the-Chrome-Web-Store-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhat if I want to restrict access to certain users or prevent my extension from being listed on the Chrome Web Store?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eYou can restrict access to your extension by limiting its visibility to Trusted Tester or by unlisting the extension from the Chrome Web Store.\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Which-operating-systems-and-Chrome-channels-are-affected-by-this-change-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhich operating systems and Chrome channels are affected by this change?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eAs of May 2015, these changes are effective for all Windows channels starting with Chrome 33 and for all Mac channels starting with Chrome 44 (around end of July 2014).\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Will-this-affect-my-ability-to-develop-my-extensions-on-Windows-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWill this affect my ability to develop my extensions on Windows?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eNo. You can still load unpacked extensions in \u003ca href\u003d\"http://developer.chrome.com/extensions/getstarted.html#unpacked\"\u003edeveloper mode\u003c/a\u003e on Windows and Mac.\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Why-couldn-t-this-problem-be-solved-by-having-a-setting-option-to-load-extensions-that-are-not-hosted-in-the-Chrome-Web-Store-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhy couldn't this problem be solved by having a setting/option to load extensions that are not hosted in the Chrome Web Store?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eUnlike modern mobile operating systems, Windows and Mac do not sandbox applications. Hence we wouldn’t be able to differentiate between a user opting in to this setting and a malicious downloaded program overriding the user’s desired setting.\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-are-the-supported-deployment-options-for-extensions-after-this-change-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhat are the supported deployment options for extensions after this change?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eApart from users installing extensions from the Chrome Web Store, the following deployment options will be supported:\u003cbr /\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eFor OSX and Linux, extensions can be installed via a \u003c/span\u003e\u003ca href\u003d\"http://developer.chrome.com/extensions/external_extensions.html#preferences\" style\u003d\"background-color:transparent\"\u003epreferences JSON file\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eFor Windows, extensions can be installed via the \u003c/span\u003e\u003ca href\u003d\"http://developer.chrome.com/extensions/external_extensions.html#registry\" style\u003d\"background-color:transparent\"\u003eWindows registry\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eIn the Windows registry and in an OS X preferences JSON file, ensure that the update_url registry key points to the following URL: \u003c/span\u003e\u003ca href\u003d\"https://clients2.google.com/service/update2/crx\" style\u003d\"background-color:transparent\"\u003ehttps://clients2.google.com/service/update2/crx\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e. Local .crx installs via the path registry key are deprecated. Note that this deployment option works only for Chrome Web Store hosted extensions, and update_url cannot point to any other host other than \u003c/span\u003e\u003ca href\u003d\"https://clients2.google.com/service/update2/crx\" style\u003d\"background-color:transparent\"\u003ehttps://clients2.google.com/service/update2/crx\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eFor Enterprises, we’ll continue to support \u003c/span\u003e\u003ca href\u003d\"https://support.google.com/chrome/a/answer/188453?hl\u003den\" style\u003d\"background-color:transparent\"\u003egroup policy\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e to install extensions, irrespective of where the extensions are hosted. Note that any extension which is not hosted on the Web Store and installed via GPO on a machine which has not joined a domain will be \u003cb\u003ehard-disabled\u003c/b\u003e. \u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Are-there-any-other-considerations-to-be-aware-of-for-extensions-that-depend-on-a-native-application-binary-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eAre there any other considerations to be aware of for extensions that depend on a native application binary?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003ePreviously when off-store extensions were supported, it was possible to have the third party application binaries and the sideloaded extension be updated in lockstep. However, extensions hosted on the Chrome Web Store are updated via the Chrome update mechanism which developers do not control. Extension developers should be careful about updating extensions that have a dependency on the native application binary (for example, extensions using \u003ca href\u003d\"https://developer.chrome.com/extensions/messaging.html#native-messaging\"\u003enative messaging\u003c/a\u003e or legacy extensions using \u003ca href\u003d\"http://developer.chrome.com/extensions/npapi.html\"\u003eNPAPI\u003c/a\u003e).\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-will-users-see-when-their-off-store-extension-is-disabled-as-a-result-of-this-rollout-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhat will users see when their off-store extension is disabled as a result of this rollout?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eThey will get a notification that says: “Unsupported extensions disabled” with a link to the following \u003ca href\u003d\"https://support.google.com/chrome/answer/2811969\"\u003esupport article\u003c/a\u003e.\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Why-do-I-see-a-bubble-about-Disable-developer-mode-extensions-when-loading-an-unpacked-extension-in-Windows-stable-beta-channels-\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWhy do I see a bubble about “Disable developer mode extensions” when loading an unpacked extension in Windows stable/beta channels?\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cspan\u003e\u003cfont size\u003d\"3\"\u003eWe do not want the developer mode to be used as an attack vector for spreading malicious extensions. Hence we’re informing users about developer mode extensions on all Windows and Mac channels and giving them an option to disable these extensions.\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/extensions-deployment-faq"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2506161099712800377"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2506161099712800377"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2506161099712800377"}],"author":[{}],"sites$pageName":{"$t":"extensions-deployment-faq"},"sites$revision":{"$t":"32"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6893724596772307700"},"published":{"$t":"2015-05-06T18:59:02.519Z"},"updated":{"$t":"2015-05-06T19:01:41.183Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-06T19:01:39.888Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"GRIT Regression Test Plan"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eMultiple projects use GRIT. This document details the regression testing plan employed by the GRIT project to ensure compatibility with all of the projects using it.\u003c/p\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eThe plan is fairly straight forward:\u003c/p\u003e\u003col style\u003d\"padding-left:25px;max-width:62em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eEach change must pass \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12.2016000747681px;max-width:66em\"\u003egrit.py unit\u003c/tt\u003e with no errors before being checked in. Ideally, the command should be tested on both Linux and Windows, since some behavior may break on case-insensitive platforms and other behavior may break on case-sensitive platforms, or may break due to different path separator characters.\u003c/li\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eProjects using GRIT should proactively contribute unit tests and regression tests that will be run as part of \u003ca href\u003d\"https://code.google.com/p/grit-i18n/wiki/RegressionTestPlan\" style\u003d\"color:rgb(0,0,204)\"\u003egrit.py unit \u003c/a\u003eto ensure any functionality they require does not get modified by accident.\u003c/li\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eWhen a project reports that a new version of GRIT has broken functionality for that project, the GRIT team and folks on the project should work together to get a regression test added.\u003c/li\u003e\u003c/ol\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eIndividual projects, of course, may put in place extensive tests in their own repository that further help to ensure that a new revision of GRIT does not break them. For example, when the revision of GRIT used is changed in the \u003ca href\u003d\"http://www.chromium.org/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eChromium project\u003c/a\u003e, the change would normally pass through that project's \u003ca href\u003d\"http://www.chromium.org/developers/testing/try-server-usage\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003etry servers\u003c/a\u003e or \u003ca href\u003d\"http://dev.chromium.org/developers/testing/commit-queue\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ecommit queue\u003c/a\u003e which would help catch any new behavior of GRIT breaking the project's test suite.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5837297656848244278"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/tools-we-use-in-chromium/grit/grit-regression-test-plan"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6893724596772307700"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6893724596772307700"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6893724596772307700"}],"author":[{"name":{"$t":"Jói Sigurðsson"},"email":{"$t":"joi@chromium.org"}}],"sites$pageName":{"$t":"grit-regression-test-plan"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5837297656848244278"},"published":{"$t":"2015-05-06T18:54:51.686Z"},"updated":{"$t":"2015-05-06T18:59:31.195Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-06T18:59:29.376Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"GRIT"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eGRIT is the internationalization tool used by the \u003ca href\u003d\"http://www.chromium.org/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eChromium\u003c/a\u003e projects (the foundation for the \u003ca href\u003d\"http://www.google.com/chrome\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eGoogle Chrome\u003c/a\u003e browser) and for several internal projects at Google.\u003c/p\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eGRIT is designed to be flexible and extensible enough to use for various different types of projects, although to date it has primarily been used for client-side software projects targeting Windows, Mac and Unix platforms.\u003c/p\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eGRIT requires Python 2.6 or later.\u003c/p\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif;font-size:13.1199998855591px\"\u003eFurther resources:\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:13.1199998855591px;line-height:16.3999996185303px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/tools-we-use-in-chromium/grit/grit-users-guide\"\u003eUser's Guide\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:13.1199998855591px;line-height:16.3999996185303px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/tools-we-use-in-chromium/grit/grit-design-overview\"\u003eDesign Overview\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:13.1199998855591px;line-height:16.3999996185303px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/tools-we-use-in-chromium/grit/grit-regression-test-plan\"\u003eRegression Test Plan\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:13.1199998855591px;line-height:16.3999996185303px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/tools-we-use-in-chromium/grit/how-to-contribute-to-grit\"\u003eHow to contribute to GRIT\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4724803148756453844"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/tools-we-use-in-chromium/grit"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5837297656848244278"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5837297656848244278"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5837297656848244278"}],"author":[{"name":{"$t":"Jói Sigurðsson"},"email":{"$t":"joi@chromium.org"}}],"sites$pageName":{"$t":"grit"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2368177713753861350"},"published":{"$t":"2012-08-13T18:15:46.073Z"},"updated":{"$t":"2015-05-05T15:00:58.582Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:08:30.522Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Stack Traces From Chrome OS Crash Dumps"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eIf you need to get a stack from a BVT failure that has already been uploaded to Google Cloud Storage, there's a much easier way to do this.  See the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/sheriff-details-chromium-os\"\u003eChrome OS sheriff\u003c/a\u003e documentation under \"How to find test results/crash reports\". Look in a directory like \u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003edesktopui_MediaAudioFeedback/sysinfo/iteration.1/var/spool/crash for the chrome.dmp.txt file.  It should have a stack.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003eIf you run a test on a device using run_remote_tests and the test crashes (for example, with a Chrome sig 11) the test script will copy a minidump file back to your workstation. However, it will not automatically generate a stack trace for you.  Here's how to get one.  (Directions are based on the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/decoding-crash-dumps\"\u003eLinux and Windows instructions\u003c/a\u003e.)\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRun your test:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003e./run_remote_tests.sh --remote\u003d172.22.70.164 desktopui_MediaAudioFeedback --args 'v\u003d1'\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOutput for a crash looks like this:\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eCrashes detected during testing:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e---------------------------------------------------------------------\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echrome sig 11\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  desktopui_MediaAudioFeedback/desktopui_MediaAudioFeedback\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e---------------------------------------------------------------------\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eLook for a line with a path to the .dmp file (it didn't really generate a stack trace for you):\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e10:49:03 INFO | Generated stack trace for dump /tmp/run_remote_tests.wNYt/desktopui_MediaAudioFeedback/desktopui_MediaAudioFeedback/sysinfo/iteration.1/var/spool/crash/chrome.20120813.104825.5708.dmp\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003eThere's a core file in that directory, but you can't use it directly as the chrome binary is stripped.  We can, however, generate symbols from the chrome.debug file and use those with minidump_stackwalk to get a stack trace.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFirst, copy the dmp file so you don't need to type the long path over and over:\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003cb\u003ecp /tmp/run_remote_tests.wNYt/desktopui_MediaAudioFeedback/desktopui_MediaAudioFeedback/sysinfo/iteration.1/var/spool/crash/chrome.20120813.104825.5708.dmp ~/foo.dmp\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eMake a temporary directory like /tmp/my_symbols. Force minidump_stackwalk to generate errors about paths not found by pointing it at that directory:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003emkdir /tmp/my_symbols\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003eminidump_stackwalk ~/foo.dmp /tmp/my_symbols 2\u0026gt;\u0026amp;1 | grep \"No symbol file\" | grep \"chrome\"\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis will tell you where you need to put the debugging symbols.  It will be a path with a hash in it, like /tmp/my_symbols/chrome/\u0026lt;hash\u0026gt;:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e2012-08-13 11:31:05: simple_symbol_supplier.cc:193: INFO: No symbol file at /tmp/my_symbols/chrome/6CC67691D7F2ECBF5E95D2BEF7F11C5A0/chrome.sym\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eNow we need to generate the symbols and put them at that location.  Create the directory using the path above:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003emkdir -p /tmp/my_symbols/chrome/6CC67691D7F2ECBF5E95D2BEF7F11C5A0\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRun dump_syms with the chrome binary and directory of the chrome.debug symbol file. Substitute your own board for \"lumpy\". This step can take 1-2 minutes.\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003edump_syms /build/lumpy/opt/google/chrome/chrome /build/lumpy/usr/lib/debug/opt/google/chrome \u0026gt; /tmp/chrome.sym\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eMove the symbol file into the path above:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003emv /tmp/chrome.sym /tmp/my_symbols/chrome/6CC67691D7F2ECBF5E95D2BEF7F11C5A0/\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFinally, you can run minidump_stackwalk to get a stack trace. It will look automatically for chrome/\u0026lt;hash\u0026gt; under the /tmp/my_symbols directory:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cb\u003eminidump_stackwalk ~/foo.dmp /tmp/my_symbols\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you need symbols for things like shared libraries you can repeat the above process grepping the path-not-found errors for things like \"libglsl.so\" instead of \"chrome\". See the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/decoding-crash-dumps\"\u003eLinux instructions\u003c/a\u003e for details.\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8468463690733929826"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/crash-reporting/stack-traces-from-chrome-os-crash-dumps"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2368177713753861350"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2368177713753861350"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2368177713753861350"}],"author":[{"name":{"$t":"James Cook"},"email":{"$t":"jamescook@chromium.org"}}],"sites$pageName":{"$t":"stack-traces-from-chrome-os-crash-dumps"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"XCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3337337385336389213"},"published":{"$t":"2013-06-19T03:23:26.555Z"},"updated":{"$t":"2015-05-05T15:00:45.405Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-05-05T15:00:42.843Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Telemetry: Add a Measurement"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Are-you-sure-you-want-to-add-a-measurement-\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eAre you sure you want to add a measurement?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-is-a-measurement-\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eWhat is a measurement?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-about-Timeline-Based-Measurement-\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eHow about Timeline-Based Measurement?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-I-think-I-need-to-write-a-new-measurement-now-what-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eI think I need to write a new measurement, now what?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Are-you-sure-you-want-to-add-a-measurement-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAre you sure you want to add a measurement?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eWriting a good measurement is really hard.  We already have a bunch of measurements in \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;background-color:rgb(239,239,239);vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/measurements/\"\u003etools/perf/measurements\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e for you to use.  If you are looking to write a new benchmark, you probably just need to add or modify an existing story set \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eand you might need to add new metrics to an existing measurement.  \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eThink twice before you write another measurement\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-What-is-a-measurement-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhat is a measurement?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA measurement is a python class that obtains a set of Numbers about a Page.  Measurements must work for \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eall\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e pages, not just one specific page.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor example, let’s say my users often go to a specific page, click a button, and scroll a div that shows up.  I could measure any number of things:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHow long it takes to go to that URL in a fresh tab until the div shows up\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHow smoothly I can scroll a div\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHow much time I spend in key WebKit systems: javascript, style, layout, paint, compositing\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHow much the memory footprint varies as I scroll the div\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHow much time I spend decoding images and painting the page\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThese are all examples of measurements.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-How-about-Timeline-Based-Measurement-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow about Timeline-Based Measurement?\u003c/span\u003e\u003c/h2\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;line-height:17.25px;white-space:pre-wrap\"\u003eTimeline-Based Measurement is a new and preferred way for computing Telemetry metrics from traces in a unified manner. The code is contained in \u003c/span\u003e\u003c/font\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/telemetry/telemetry/web_perf/\" style\u003d\"font-family:Courier New;font-size:15px;line-height:17.25px;white-space:pre-wrap;background-color:rgb(238,238,238)\"\u003etools/telemetry/telemetry/web_perf\u003c/a\u003e. \u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003eFor details about this approach, see the following documents: \r\n\u003ca href\u003d\"https://docs.google.com/document/d/10G0PbePQOwJao57Mu6Xr7Fx0o2ng8fwZ33wUqpnsyog\"\u003eWhy choose TimelineBasedMeasurement over other measurements?\u003c/a\u003e \u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003e\u003ca href\u003d\"https://docs.google.com/document/d/1cx_yplQQUVtIka5DD846kcfheIdIoTHfCL0dH93ezA8/edit?usp\u003dsharing\"\u003eHow does TimelineBasedMeasurement work?\u003c/a\u003e \u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003cspan\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-I-think-I-need-to-write-a-new-measurement-now-what-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eI think I need to write a new measurement, now what?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ePlease email \u003c/span\u003e\u003ca href\u003d\"mailto:telemetry@chromium.org\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003etelemetry@chromium.org\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e with details about what you are trying to measure.  We can help you get started and ensure that there are not existing measurements that you could use.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4695032730150632508"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/telemetry/add_a_measurement"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3337337385336389213"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3337337385336389213"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3337337385336389213"}],"author":[{}],"sites$pageName":{"$t":"add_a_measurement"},"sites$revision":{"$t":"15"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2557903603901208053"},"published":{"$t":"2014-08-26T14:50:40.295Z"},"updated":{"$t":"2015-04-28T22:36:48.096Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-26T14:50:40.295Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2014-08-26 at 10.49.51 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2557903603901208053"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9207956454205601387"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/telemetry/performance-try-bots/Screen%20Shot%202014-08-26%20at%2010.49.51%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2557903603901208053"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2557903603901208053"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2557903603901208053"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2557903603901208053"}],"author":[{"name":{"$t":"Annie Sullivan"},"email":{"$t":"sullivan@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4189283535224483621"},"published":{"$t":"2014-08-26T14:51:18.761Z"},"updated":{"$t":"2015-04-28T22:36:48.096Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-26T14:51:18.761Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2014-08-26 at 10.49.28 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4189283535224483621"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9207956454205601387"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/telemetry/performance-try-bots/Screen%20Shot%202014-08-26%20at%2010.49.28%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4189283535224483621"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4189283535224483621"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4189283535224483621"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4189283535224483621"}],"author":[{"name":{"$t":"Annie Sullivan"},"email":{"$t":"sullivan@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6335671219326649450"},"published":{"$t":"2015-04-28T21:37:01.456Z"},"updated":{"$t":"2015-04-28T21:37:01.496Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-28T21:37:01.456Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"benchmark-organization-diagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6335671219326649450"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4695032730150632508"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/telemetry/benchmark-organization-diagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6335671219326649450"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6335671219326649450"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6335671219326649450"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6335671219326649450"}],"author":[{"name":{"$t":"Ethan Kuefner"},"email":{"$t":"eakuefner@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4023324726177346031"},"published":{"$t":"2015-04-20T20:22:30.295Z"},"updated":{"$t":"2015-04-28T19:38:03.842Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-28T19:38:02.808Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Lucid Sleep"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOverview\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Kernel\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eKernel\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Power-Manager\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ePower Manager\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Handling-user-activity\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eHandling user activity\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Shill\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eShill\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eChrome\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Freezing-Renderers\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eFreezing Renderers\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Properly-handling-the-lock-screen\"\u003e\u003cstrong\u003e5.1.1 \u003c/strong\u003eProperly handling the lock screen\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Dealing-with-renderers-that-may-receive-push-messages\"\u003e\u003cstrong\u003e5.1.2 \u003c/strong\u003eDealing with renderers that may receive push messages\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Interacting-with-the-GPU-process\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003eInteracting with the GPU process\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h1\u003e\r\n\r\n\r\n\u003cp\u003eSome recent Chrome devices have the ability to wake up from a suspended state\r\nto perform work. Potential tasks include:\u003c/p\u003e\r\n\r\n\u003cul\u003e\r\n \u003cli\u003e Associating with a known WiFi access point that has just come into range\r\n \u003c/li\u003e\u003cli\u003e Updating user data in response to a received push message\r\n \u003c/li\u003e\u003cli\u003e Synchronizing with app servers at the request of an app\r\n \u003c/li\u003e\u003cli\u003e Performing system maintenance like trimming SSDs or checking the battery level\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003cp\u003eTo minimize power consumption while performing tasks and external indications\r\nthe device is performing work, the device uses a hybrid power state called\r\nLucid Sleep. Effectively using this state requires coordination between all\r\nparts of the system, from the kernel to the system daemons to the Chrome\r\nbrowser. \u003c/p\u003e\r\n\r\n\u003cp\u003eThis page describes the interactions between the system components to\r\ncoordinate Lucid Sleep. It is intended to help with firmware and kernel\r\nimplementations and troubleshooting of this feature on Chrome devices that\r\nsupport it.\u003c/p\u003e\r\n\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-Kernel\" /\u003eKernel\u003c/h1\u003e\r\n\r\n\r\n\u003cp\u003eWhen a Chrome device is suspending, the kernel performs the following steps:\u003c/p\u003e\r\n\r\n\u003col\u003e\r\n \u003cli\u003e Userspace processes are frozen. Every userspace process is removed from the\r\nscheduler’s run queue and no more CPU cycles are allocated.\r\n \u003c/li\u003e\u003cli\u003e Select kernel threads are frozen, depending on the device. Exactly which\r\nthreads are frozen depends on the hardware configuration; in some cases, no\r\nkernel threads are frozen.\r\n \u003c/li\u003e\u003cli\u003e Hardware components are suspended, for example the display panel is turned off,\r\nthe hard drive is stopped, and USB ports are powered down.\r\n \u003c/li\u003e\u003cli\u003e All non-boot CPUs are disabled.\r\n \u003c/li\u003e\u003cli\u003e The kernel programs the underlying hardware with a list of interrupt sources\r\nthat are allowed to wake up the system, for example the keyboard or power\r\nbutton.\r\n \u003c/li\u003e\u003cli\u003e The kernel puts the boot CPU into a low-power state so that no code is running\r\non that CPU.\r\n\u003c/li\u003e\u003c/ol\u003e\r\n\r\n\u003cp\u003eResuming a Chrome device is essentially the reverse of the suspend sequence:\u003c/p\u003e\r\n\r\n\u003col\u003e\r\n \u003cli\u003e The hardware determines that a wakeup event has occurred and delivers an\r\ninterrupt to the boot CPU.\r\n \u003c/li\u003e\u003cli\u003e The boot CPU starts running the kernel code.\r\n \u003c/li\u003e\u003cli\u003e Non-boot CPUs are re-enabled.\r\n \u003c/li\u003e\u003cli\u003e Hardware components are resumed.\r\n \u003c/li\u003e\u003cli\u003e Any frozen kernel threads are thawed.\r\n \u003c/li\u003e\u003cli\u003e Userspace processes are thawed and the system resumes normal activity.\r\n\u003c/li\u003e\u003c/ol\u003e\r\n\r\n\u003cp\u003eTo support Lucid Sleep, the kernel allows userspace to expand the list of\r\ninterrupt sources that can trigger wakeup events. It is also possible to\r\nspecify sources that trigger Lucid Sleep versus a full system resume. Hardware\r\ncomponents that can trigger wakeup events must run independently in a low-power\r\nstate without kernel support. Conversely, kernel drivers for components that do\r\nnot trigger wakeup events must not re-initialize the hardware during Lucid\r\nSleep.\u003c/p\u003e\r\n\r\n\u003cp\u003eFor example, a device receives a push message over the network. The power\r\nmanager adds the Network Interface Card (NIC) to the list of hardware\r\ncomponents that can trigger a wakeup interrupt. It also adds the display panel\r\nand USB ports to the list of components that must not re-initialize during\r\nLucid Sleep. At suspend time the NIC driver puts the NIC into a low-power state\r\nrather than turning it off. Other suspend operations proceed as normal.\u003c/p\u003e\r\n\r\n\u003cp\u003eAfter a wakeup event is triggered and before hardware components are resumed,\r\nthe kernel determines if the wakeup event should trigger Lucid Sleep or a full\r\nresume and saves this value. When the hardware components are resumed, the\r\ndevice drivers query the kernel to determine whether the wakeup is for Lucid\r\nSleep. If so, and userspace has requested that that hardware remain off, the\r\ndriver skips the remainder of re-initialization steps. After userspace\r\nprocesses thaw, a process can also query the kernel via the sysfs interface to\r\ndetermine if the wakeup event triggered Lucid Sleep.\u003c/p\u003e\r\n\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-Power-Manager\" /\u003ePower Manager\u003c/h1\u003e\r\n\r\n\r\n\u003cp\u003eThe power manager provides a mechanism for notifying the system daemons and\r\nChrome when the device is in Lucid Sleep. This mirrors the mechanism used\r\nfor notifying the system daemons when the Chrome device is about to suspend. A\r\nprocess can register with the power manager on start up. When the system enters\r\nLucid Sleep, the power manager notifies registered processes by sending out a\r\nDarkSuspendImminent D-Bus signal. This signal is the only external indication\r\nthat the system is in Lucid Sleep. \u003c/p\u003e\r\n\r\n\u003cp\u003eWhen a device enters Lucid Sleep, the power manager also detects that the\r\nwakeup event was not user-triggered and it should suspend the device again as\r\nsoon as possible. The DarkSuspendImminent signal both announces Lucid Sleep and\r\nsignals that suspension is imminent.\u003c/p\u003e\r\n\r\n\u003cp\u003eWhen a suspend operation successfully completes (and userspace processes have\r\nbeen thawed by the kernel), the power manager queries the kernel to see if the\r\ncurrent resume operation is from Lucid Sleep. If so, it sends out a\r\nDarkSuspendImminent signal and waits for all applications that have registered\r\nto receive the signal to report on readiness to suspend. After all registered\r\napplications have reported readiness or the maximum delay has passed, the power\r\nmanager again instructs the kernel to suspend the system.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Handling-user-activity\" /\u003eHandling user activity\u003c/h2\u003e\r\n\r\n\r\n\u003cp\u003eOccasionally, a user may start to interact with the Chrome device while it is\r\nin the middle of Lucid Sleep. To ensure that all hardware components are\r\nproperly resumed, in this case the power manager instructs the kernel to\r\nperform a test suspend. The normal suspend sequence is interrupted after\r\nsuspending hardware components, and the kernel immediately jumps to the step of\r\nresuming hardware components in the resume sequence. This ensures that all\r\nhardware components are ready before the user starts interacting with the\r\nsystem.\u003c/p\u003e\r\n\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-Shill\" /\u003eShill\u003c/h1\u003e\r\n\r\n\r\n\u003cp\u003eShill, the connection manager, decides what WiFi-related actions—such as\r\nprogramming the wireless NIC and setting RTC timers—to take before the system\r\ngoes into suspend, when the system wakes up in Lucid Sleep, and when the system\r\nfully resumes. The primary goals of these actions are to maintain WiFi\r\nconnectivity while the system is suspended or in Lucid Sleep and to allow the\r\nsystem to respond to important events (e.g. GCM push notifications).\u003c/p\u003e\r\n\r\n\u003cp\u003eBefore the system suspends from a fully awake or Lucid Sleep state, shill\r\nverifies whether the system’s WiFi interface is connected to a network. If the\r\nsystem is connected, shill programs the wireless NIC to wake the system if the\r\nNIC disconnects from that network, and starts an RTC timer to wake the system\r\nin Lucid Sleep to renew its IPv4 DHCP lease (or obtain a new IPv6\r\nconfiguration) when it is about to expire. If the system is not connected,\r\nshill programs the wireless NIC to independently perform periodic scans while\r\nthe system is suspended, and wake the system if any of its preferred networks\r\nare found. If the number of preferred networks is greater than the NIC\r\nwhitelist capacity, a separate RTC wake timer is started to wake the system in\r\nLucid Sleep to perform shill-initiated scans. Shill also programs the wireless\r\nNIC to wake the system upon receiving packets from whitelisted IP addresses\r\nregistered by Chrome (more details in next section).\u003c/p\u003e\r\n\r\n\u003cp\u003eWhen the system wakes up in Lucid Sleep, shill receives a wakeup reason from\r\nthe kernel. If the reason is a disconnect or detection of a preferred network,\r\nshill triggers a passive scan and attempts to establish a connection to any\r\nnetworks found. If the reason is the receipt of a packet from a whitelisted IP\r\naddress (i.e. a GCM push notification), shill does nothing and allows Chrome to\r\nhandle the packet. For any other reason, including the aforementioned RTC\r\ntimers, shill either renews DHCP leases if the system is already connected, or\r\nperforms a scan and if the system is not connected, attempts to establish a\r\nconnection.\u003c/p\u003e\r\n\r\n\u003cp\u003eWhen the system fully resumes, shill deprograms all wake on WiFi triggers on\r\nthe wireless NIC, and stops any RTC timers that shill might have started before\r\nsuspend or during Lucid Sleep. Shill will then scan for networks if the system\r\nwakes up not connected, and will resume its normal functionality thereafter.\u003c/p\u003e\r\n\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-Chrome\" /\u003eChrome\u003c/h1\u003e\r\n\r\n\r\n\u003cp\u003eThe Chrome browser software handles push messages that arrive over the network.\r\nIt registers with the power manager so that the power manager will wait for it\r\nto report readiness before suspending from Lucid Sleep. The progress of all\r\npush messages is tracked from arrival to completion. If Chrome receives a\r\nDarkSuspendImminent signal while one or more push messages are active, it waits\r\nuntil no more active push messages remain before informing the power manager\r\nthat it is ready to suspend. Additionally, any network requests started by a\r\nmessage consumer during processing can further delay Chrome before it reports\r\nreadiness to the power manager.\u003c/p\u003e\r\n\r\n\u003cp\u003eChrome also tells the NIC which connections to watch for incoming messages.\r\nCurrently, connections to Google Cloud Messaging (GCM) servers are supported.\r\nAfter Chrome establishes a connection to the GCM server, it informs the NIC of\r\nits IP address. While the system is suspended the NIC continues listening for\r\nnetwork activity and when a packet arrives from the IP address of the GCM\r\nserver, the NIC sends an interrupt to the boot CPU to wake the system into\r\nLucid Sleep.\u003c/p\u003e\r\n\r\n\u003cp\u003eTo maintain a connection with the GCM servers, Chrome sends a heartbeat message\r\nto the server at regular intervals. A specialized timer (the \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/components/timers/alarm_timer_chromeos.h\"\u003eAlarmTimer\u003c/a\u003e) is used to set a Real Time Clock (RTC) alarm. The RTC is a hardware timer\r\nthat runs even while the system is suspended and sends an interrupt to the boot\r\nCPU to wake the system into Lucid Sleep.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Freezing-Renderers\" /\u003eFreezing Renderers\u003c/h2\u003e\r\n\r\n\r\n\u003cp\u003eIf improperly handled, frequently waking up the system can consume a\r\nsignificant amount of battery resources. In addition to conserving power by not\r\nresuming power-hungry components like the display panel, while in Lucid Sleep\r\nChrome minimizes its usage of the CPU.\u003c/p\u003e\r\n\r\n\u003cp\u003eChrome has a multi-process architecture (for more details see \u003ca href\u003d\"http://www.chromium.org/developers/design-documents/multi-process-architecture\"\u003ehere\u003c/a\u003e.) All apps, extensions, and web pages run inside renderer processes, which\r\nrepresent the biggest consumers of the CPU in the system. To minimize the power\r\nthey consume (for example by running the CPU at a high load), Chrome freezes\r\nrenderer processes at the initial suspend time and thaws them only after a full\r\nresume. \u003c/p\u003e\r\n\r\n\u003cp\u003eThe Linux kernel mechanism of control groups (\u003ca href\u003d\"https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt\" rel\u003d\"nofollow\"\u003ecgroups\u003c/a\u003e) is used. Freezing processes in a cgroup works the same way as freezing\r\nuserspace processes at suspend time: the kernel simply removes the processes\r\nfrom the scheduler’s run queue. Since Chrome freezes its renderer processes\r\nbefore the system suspends, those processes remain frozen even after the system\r\nresumes and are thawed only when Chrome explicitly thaws them. Processes stay\r\nfrozen for the duration of Lucid Sleep and CPU load is minimized.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Properly-handling-the-lock-screen\" /\u003eProperly handling the lock screen\u003c/h3\u003e\r\n\r\n\r\n\u003cp\u003eEither users or an enterprise policy can set a Chrome preference that locks the\r\nscreen when the system suspends. Like most parts of the system user interface,\r\nthe lock screen runs inside a renderer process. Common side effects of freezing\r\nthe lock screen operation include a noticeable lag when the system fully\r\nresumes and dropped keystrokes. In some cases, users may need to re-type their\r\npasswords.\u003c/p\u003e\r\n\r\n\u003cp\u003eTo address this, the lock screen renderer is given special treatment. If a user\r\nrequests locking the screen when the system suspends, Chrome puts the lock\r\nscreen renderer process in a separate cgroup from the other renderers. The lock\r\nscreen renderer remains unfrozen and responsive when the system fully resumes.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Dealing-with-renderers-that-may-receive-push-messages\" /\u003eDealing with renderers that may receive push messages\u003c/h3\u003e\r\n\r\n\r\n\u003cp\u003eSince all web applications as well as Chrome apps and extensions run inside a\r\nrenderer, a push message cannot be fully handled if the destination renderer\r\nhas no CPU cycles. So some renderers do need to remain active during Lucid\r\nSleep.\u003c/p\u003e\r\n\r\n\u003cp\u003eChrome decides whether or not to freeze a renderer\r\nprocess when the renderer is first spawned. For example, for Chrome apps and\r\nextensions, Chrome looks at the permissions that the app/extension has\r\nrequested in its manifest. If it has requested the “gcm” permission, Chrome\r\nkeeps the renderer out of the group of renderers to freeze at suspend time.\r\nThis ensures that when a push message arrives it can be handled as quickly as\r\npossible.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Interacting-with-the-GPU-process\" /\u003eInteracting with the GPU process\u003c/h2\u003e\r\n\r\n\r\n\u003cp\u003eChrome uses a dedicated process to interact with the GPU on the system. This\r\nprocess is not frozen during Lucid Sleep and can continue to respond to\r\nrequests to render objects to the screen. Though the renderers themselves may\r\nbe frozen and unable to make requests to the GPU process, the main browser\r\nprocess remains active and can issue updates.\u003c/p\u003e\r\n\r\n\u003cp\u003eThis has implications for the display panel component, which is off during\r\nLucid Sleep. Any attempts by the GPU process to update the contents of the\r\nscreen result in errors, causing loss of context and forced reallocation of\r\nresources. In addition to affecting GPU performance, repeatedly losing and\r\nallocating a context (often multiple times per second) add a significant load\r\nto the CPU, increasing the amount of power consumed during Lucid Sleep and\r\nreducing the system’s overall battery life.\u003c/p\u003e\r\n\r\n\u003cp\u003eTo avoid consuming unnecessary resources, Chrome stops its compositor from\r\nupdating the screen and prevents rendering requests from reaching the GPU\r\nprocess. If the user has configured the screen to lock when the system\r\nsuspends, Chrome waits until the contents of the lock screen are visible before\r\ndirecting the compositor to stop rendering. The delay allows the contents of\r\nthe user’s screen to remain invisible and secure when the system resumes.\u003c/p\u003e\r\n\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/lucid-sleep"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4023324726177346031"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4023324726177346031"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4023324726177346031"}],"author":[{}],"sites$pageName":{"$t":"lucid-sleep"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4723945718499501890"},"published":{"$t":"2009-11-19T17:03:09.230Z"},"updated":{"$t":"2015-04-27T04:16:56.655Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-27T04:16:52.465Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Firmware Boot and Recovery"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Abstract\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eAbstract\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Potential_Problems_06602847948\"\u003e\u003cstrong\u003e2 \u003c/strong\u003ePotential problems\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Firmware_6345705660060048_1740\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Design_Decisions_8644751217216\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eDesign decisions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Boot_needs_to_start_securely_5\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eBoot needs to start securely\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Writable_firmware_should_have__7966560075305942\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eWritable firmware should have a backup\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Recovery_firmware_should_be_re_024671708017260596\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eRecovery firmware must be read-only\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Recovery_firmware_does_not_nee_43765456105130307\"\u003e\u003cstrong\u003e3.4 \u003c/strong\u003eRecovery firmware does not need to access the network\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Recovery_firmware_should_tell_\"\u003e\u003cstrong\u003e3.5 \u003c/strong\u003eRecovery firmware should tell the user how to recover\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Users_should_be_able_to_manual\"\u003e\u003cstrong\u003e3.6 \u003c/strong\u003eUsers must be able to manually trigger recovery mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Support_developers_l33t_users_\"\u003e\u003cstrong\u003e3.7 \u003c/strong\u003eSupport developers / l33t users installing their own software\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#EEPROM_Map_19483716413378716_0_8527987941869014\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eEEPROM map\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware-block-descriptions\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eFirmware block descriptions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Boot_Stub_2175902035087347_738\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eBoot stub\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Firmware_A_B_Setup_41671303566\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003eFirmware (A/B) setup\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Firmware_A_B_Bootstrap_6854730_9843585162384771\"\u003e\u003cstrong\u003e5.3 \u003c/strong\u003eFirmware (A/B) boot loader\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Boot_Log_909660461358726_02223_241900222824606\"\u003e\u003cstrong\u003e5.4 \u003c/strong\u003eBoot log\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Recovery_Firmware_325963526964_9310128691004004\"\u003e\u003cstrong\u003e5.5 \u003c/strong\u003eRecovery firmware\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Recovery_Image_999069100245833_9862531434570179\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eRecovery image\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Recovery_via_Chrome_OS_2183209_6000941713093587\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003eRecovery via Chromium OS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Making_Recovery_Images_Read_On\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003eMaking recovery images read-only\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Using_Recovery_Mode_to_load_De\"\u003e\u003cstrong\u003e6.3 \u003c/strong\u003eUsing recovery mode to load developer mode firmware/software\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Boot_Flowchart_033826657570898\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eBoot flowchart\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Other-notes\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eOther notes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Verification_of_the_Rest_of_ro\"\u003e\u003cstrong\u003e8.1 \u003c/strong\u003eVerification of the rest of the rootfs\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#When_to_Verify_the_Boot_Proces\"\u003e\u003cstrong\u003e8.2 \u003c/strong\u003eWhen to verify the boot process\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Handling_Returned_Netbooks_578\"\u003e\u003cstrong\u003e8.3 \u003c/strong\u003eHandling returned systems\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Testing_17694905913316072_043226863012933325\"\u003e\u003cstrong\u003e8.4 \u003c/strong\u003eTesting\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Open_Issues_6727640628814697_9\"\u003e\u003cstrong\u003e9 \u003c/strong\u003eOpen issues\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#What_Else_Do_We_Need_To_Verify\"\u003e\u003cstrong\u003e9.1 \u003c/strong\u003eWhat else do we need to verify?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Can_we_log_firmware_crashes_54_8565273169739532\"\u003e\u003cstrong\u003e9.2 \u003c/strong\u003eCan we log firmware crashes?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Chain_of_verification_on_ARM_2_45279574090983055\"\u003e\u003cstrong\u003e9.3 \u003c/strong\u003eChain of verification on ARM?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Support_for_Trusted_Platform_M_472807140635382\"\u003e\u003cstrong\u003e9.4 \u003c/strong\u003eSupport for Trusted Platform Module (TPM)?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Abstract\" /\u003eAbstract\u003c/h2\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe layout and structure of firmware for Chromium OS is designed for security (see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified Boot\u003c/a\u003e documentation), recovery and development.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAll firmware will contain a recovery code path, which will restore the machine to its original Chromium OS state. This recovery code path will be initiated either when any chain in the boot path is not verified or when a user manually triggers recovery mode, likely via an explicit recovery button on the device.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eChromium OS wants to support developers as well. Developers are provided with a means of running alternate software. In the alternate boot paths, the user is notified that they are not running a boot path provided as part of Chromium OS.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe boot and recovery procedures outlined will be implemented and required for all Chromium OS platforms regardless of architecture (ARM/Intel/etc...).\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003cp\u003e\r\n\u003c/p\u003e\r\n\r\n\u003cp\u003e\r\n This document describes the firmware boot process, including detection and recovery of corrupted or hacked firmware/software.\r\n\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"Potential_Problems_06602847948\" /\u003e\r\n Potential problems\r\n\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n The firmware boot process must be able to detect the following problems and, if possible, repair them.\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"Firmware_6345705660060048_1740\" /\u003e\r\n Firmware\r\n\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003eIncomplete update: An update of the firmware is interrupted. This leaves the portion of the firmware which was being updated in an unknown or corrupt state. For example, if the update is interrupted after a firmware block is erased but before it is reprogrammed, that block is empty.\r\n \u003c/li\u003e\r\n \u003cli\u003eAttack: An attacker compromises the software and is able to reprogram the firmware. For example, an exploit of an unpatched kernel vulnerability. In this case, both the main and backup firmware may be compromised.\r\n \u003c/li\u003e\r\n \u003cli\u003eCorruption: The EEPROM holding the firmware becomes corrupted in the sectors containing writable/updatable firmware.\r\n \u003c/li\u003e\r\n \u003c/ol\u003e\r\n\u003c/div\u003e\r\n\r\n\u003cdiv\u003e\r\n \u003cb\u003eSoftware\u003c/b\u003e\r\n\u003c/div\u003e\r\n\r\n\u003cdiv\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003eIncomplete update: An update of the software on the drive is interrupted. This leaves the rootfs partition in an unknown state.\r\n \u003c/li\u003e\r\n \u003cli\u003eAttack: An attacker compromises the software and is able to rewrite the data on the drive (rootfs or partition table).\r\n \u003c/li\u003e\r\n \u003cli\u003eMalicious user: A malicious user installs developer mode onto the device, leaving behind a trojan, then returns the device.\r\n \u003c/li\u003e\r\n \u003cli\u003eCorruption: The drive becomes corrupted in the partition table or rootfs partition.\r\n \u003c/li\u003e\r\n\u003cli\u003eCrash: Device crashes on boot due to bad software. For example, the device is updated with the wrong image. This prevents the normal autoupdate process from running.\u003c/li\u003e\r\n \u003c/ol\u003e\r\n \r\n\r\n \r\n\u003cdiv\u003e\r\n \u003cb\u003eOut of scope\u003c/b\u003e\r\n \u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n The following problems are outside the scope of this document in its current form:\r\n\u003c/div\u003e\r\n\r\n\u003cdiv\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003e\r\n An attacker with physical access to the device opens the device and alters its innards. This includes:\r\n \u003c/li\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n Jumpering the EEPROM to gain write access to the read-only portion.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Replacing the EEPROM.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Otherwise altering the circuit board (adding piggyback chips, etc).\r\n \u003c/li\u003e\r\n \u003c/ul\u003e\r\n \u003cli\u003e\r\n Exploits involving the normally-writable data partition. \r\n \u003c/li\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n Changing bookmarks to point to sites which download HTML5 malware, etc.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Malformed bookmarks file or image which causes a buffer overrun when parsed\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Changing the preferred wireless network to a malicious one which logs/alters packets\r\n \u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eExploits involving other processors (embedded controller, modem processor, etc.)\u003c/li\u003e\r\n\u003cul\u003e\r\n \u003c/ul\u003e\r\n \r\n\u003cul\u003e\r\n \u003c/ul\u003e\r\n \u003c/ol\u003e\r\n \r\n\r\n \r\n\u003ch2\u003e\u003ca name\u003d\"Design_Decisions_8644751217216\" /\u003e\r\n Design decisions\r\n \u003c/h2\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Boot_needs_to_start_securely_5\" /\u003e\r\n Boot needs to start securely\r\n \u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIn order to attempt a secure boot, the initial boot stub needs to perform a minimum level of initialization to verify the next piece of boot code before handing off to that code.\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n To prevent accidental or intentional corruption of the known-good boot stub, this code must be in a portion of memory which is not field-writable. Many EEPROM devices have an external pin (\u003cu\u003eWP\u003c/u\u003e) which can be pulled low to write protect the upper portion of the EEPROM. This has a number of benefits:\r\n\u003c/div\u003e\r\n\u003cul\u003e\r\n \u003cli\u003e\r\n Devices are writable at time of manufacture (as opposed to true ROMs, which are fixed at time of ROM manufacture).\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Devices can be made writable for firmware development by simple hardware modification.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Both readable and read-only ROM are provided by a single device. Simpler board design, fewer parts, lower cost.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Any attacker who can open the case and modify the hardware to write to the protected upper portion of ROM could also simply replace a true ROM with a reprogrammed part, so this isn't significantly less secure than a true ROM.\r\n \u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\u003cdiv\u003e\r\n On ARM platforms, the initial boot ROM may be in the same package as the processor. This is even more secure compared to a separate EEPROM.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"Writable_firmware_should_have__7966560075305942\" /\u003e\r\n Writable firmware should have a backup\r\n\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n To protect against a failed firmware update, the writable portion of the firmware (responsible for doing the remainder of chipset and storage setup and then bootstrapping the kernel off the storage device) should exist in two copies. In the event the first copy is corrupt, the device can boot normally off the second copy. This is similar to the design for the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/filesystem-autoupdate\"\u003efile system\u003c/a\u003e, which has two copies of the root partition.\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"Recovery_firmware_should_be_re_024671708017260596\" /\u003e\r\n Recovery firmware must be read-only\r\n\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n Recovery firmware must be able to take over the boot process if the boot stub determines that the normal writable firmware is corrupt, or if the user manually boots the device into recovery mode.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n To prevent the recovery firmware from being corrupted by a firmware update or a software-based attack, it must be in the same read-only portion of the EEPROM as the boot stub.\r\n\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"Recovery_firmware_does_not_nee_43765456105130307\" /\u003e\r\n Recovery firmware does not need to access the network\r\n\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n The recovery process should not require firmware-level network access by the device being recovered.  The recovery procedure can involve a second computer, which is used to create recovery media (for example, a USB drive or SD card). It is assumed that second computer has network access.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n This simplifies the recovery process, since the recovery firmware only needs to bring up enough of the system to bootstrap a Linux image from local storage. That image can then take care of reflashing the EEPROM and reimaging. \r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n It is not necessary to implement a full network stack with WiFi configuration in the recovery firmware to support PXE boot. PXE boot introduces a number of complications:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eNeed to initialize more hardware to bring up wireless, keyboard, etc.\u003c/li\u003e\r\n\u003cli\u003eNeed to implement a full network stack.\u003c/li\u003e\r\n\u003cli\u003eMakes recovery an interactive process, including the user entering their SSID and WPA key, which the user may not know.\u003c/li\u003e\r\n\u003cli\u003eUnlikely to work for public WiFi access points; these often redirect http access to a login screen, navigation of which which would necessitate a full browser in the recovery firmware.\u003c/li\u003e\r\n\u003cli\u003eUnlikely to work for cellular networks (3G/4G/etc...), if that requires more complicated drivers or configuration.\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003cdiv\u003eAll of these issues would need to be resolved, and the resulting firmware must be correct at the time the device ships, because recovery mode firmware can't be updated in the field. It is unacceptable to ship a mostly-working PXE solution, assuming that the user can fall back on a second computer in the event PXE recovery fails. The only time the user would discover PXE recovery didn't work is when the user is relying on it to repair their computer.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eMore information on wireless network boot is here: \u003ca href\u003d\"http://etherboot.org/wiki/wirelessboot\" rel\u003d\"nofollow\"\u003ehttp://etherboot.org/wiki/wirelessboot\u003c/a\u003e.\u003cbr /\u003e\r\n\u003cdiv\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Recovery_firmware_should_tell_\" /\u003e\r\n Recovery firmware should tell the user how to recover\r\n \u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n If the recovery firmware finds a USB drive/SD card with a good recovery image on it, it should boot it and use that to recover. The software in that recovery image will have its own user interface to guide the user through recovery.\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n If the recovery firmware does not find a good recovery image, it needs to tell the user how to use a second computer to build that recovery image.\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n\u003cdiv\u003eThe preferred way to do this is to initialize the screen and show recovery instructions to the user, including a URL to go to in that second computer's web browser. Note that recovery instructions need to be displayed in the correct language for the user.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003eIt is desirable for the recovery instructions and/or recovery URL to include a code for the device model. This allows the destination website to:\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eProvide the proper recovery image for that device model.\u003c/li\u003e\r\n\u003cli\u003eDescribe the recovery procedure specific to that device model. For example, if the device has a SD card but no USB port, the recovery procedure would indicate that a SD card is necessary, and would not discuss the possibility of recovering using USB.\u003c/li\u003e\r\n\u003cli\u003eDisplay graphics appropriate for the device model. For example, showing the location of the USB or SD card port.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\r\n \u003c/div\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Users_should_be_able_to_manual\" /\u003e\r\n Users must be able to manually trigger recovery mode\u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n If the writable firmware and/or rootfs have valid signatures but don't work (for example, the user somehow managed to get an ARM kernel on an x86 device), the user needs to be able to force recovery mode to run.\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n This can be done by having a physical reset button somewhere on the device. When this button is pressed during power-on, the device goes straight to the recovery firmware without even looking at the writable firmware or file system.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSome options for the recovery button:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eIt could be a button attached to a GPIO on the main processor. In this case, the boot stub would initialize the GPIO and read its state at boot time.\u003c/li\u003e\r\n\u003cli\u003eIt could be a button attached to a subprocessor such as the Embedded Controller (EC). In this case, the boot stub would need to request the button state from the EC at boot time.\u003c/li\u003e\r\n\u003cli\u003eIt could be one of the keys on the keyboard, though this creates the undesirable possibility of accidentally entering recovery mode. \u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThis is undesirable if the only interface to the keyboard is USB, because USB firmware is more complex and the USB hardware interface can take a significant amount of time to initialize. \u003c/li\u003e\r\n\u003cli\u003eSome devices use a subprocessor to read the keyboard. In this case, initiating recovery mode is much like the previous option.\u003c/li\u003e\r\n\u003cli\u003eThe keyboard could bring out the press-state of one of its keys to a separate I/O line, which could be attached to a GPIO on the processor or to a subprocessor.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\r\n\u003cdiv\u003eSince the recoverability of Chromium OS is one of its key features, we seek to have a dedicated \"recovery mode\" button.\u003c/div\u003e\r\n\u003c/div\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Support_developers_l33t_users_\" /\u003e\r\n Support developers / l33t users installing their own software\r\n \u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n To provide a relatively trustable boot for the majority of users, we need to control all the read-only firmware at the beginning of the boot process.\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003e\r\n To support developers, at some point during the boot process, we need to hand off to code self-signed by someone else.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe initial devices will allow hand off at the point the kernel is loaded and its embedded signature is checked.  This can produce one of three results:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eTrusted kernel: The kernel has a valid signature, and the signing key is known to the firmware.  This is the normal case for production devices.\u003c/li\u003e\r\n\u003cli\u003eDeveloper kernel: The kernel has a valid signature, but the key used to sign the kernel is not known to the firmware.  This is the case when a developer builds and self-signs their own kernel.\u003c/li\u003e\r\n\u003cli\u003eCorrupt kernel: The kernel fails its signature check.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eOnce the chain of trust departs from the standard Chromium OS boot chain, we need to indicate this clearly to the user of the device. This prevents malicious attackers from giving users a modified version of Chromium OS without the user knowing. We likely will need to show a warning screen which includes the following elements:\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli\u003eA warning that the standard image of Chromium OS is not running\u003c/li\u003e\r\n\u003cli\u003eA means of reverting back to the standard Chromium OS image\u003c/li\u003e\r\n\u003cli\u003eA means of allowing the user/developer to proceed down the \"untrusted\" path\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIt is desirable for the warning screen to have a timeout, so that Chromium OS devices with developer images can be used in unattended applications (for example, as a media server).  The timeout should be sufficiently long that a user can read and respond to it - for example, at least 30 seconds.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSince language settings will not be available at this stage of the boot process, any messaging will likely need to be internationalized and displayed in all possible languages.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003cdiv\u003e\r\n\r\n\u003cdiv\u003e\r\n \r\n\u003ch2\u003e\u003ca name\u003d\"EEPROM_Map_19483716413378716_0_8527987941869014\" /\u003e\r\n EEPROM map\r\n \u003c/h2\u003e\r\n \u003ca name\u003d\"EEPROM_Map\" /\u003e\r\n \r\n\u003cdiv\u003eHere is an early guess at sizes and layout of the EEPROM. These sizes may change as we progress with implementation.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"http://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery/eeprom-map.png?attredirects\u003d0\" imageanchor\u003d\"1\" rel\u003d\"nofollow\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1258650191714/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery/eeprom-mappng\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware-block-descriptions\" /\u003eFirmware block descriptions\u003c/h2\u003e\r\n\u003c/div\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Boot_Stub_2175902035087347_738\" /\u003e\r\n Boot stub\r\n \u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n Must be at the top of EEPROM, since most processors jump to the top of memory (0xFFFFFFF0) after internal initialization.\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n Contains the \"root key\" - the official public key used to verify the signature of the next stage of firmware. The private key is not contained on the device, and must be protected from all unauthorized access. To reduce exposure of the private root key, the private root key will be used to sign a second date-limited or numbered key stored in the rewritable firmware, which is then used to sign that firmware. Validation of the date or key number could be done via a TPM module.\u003cbr /\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cb\u003ePseudocode\u003c/b\u003e\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003e\r\n Initialize processor and RAM (and implicitly, those parts of the north bridge necessary to initialize RAM), using conservative timings.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n If user-forced recovery mode, skip to attempt loading recovery firmware. (The recovery button asserts an I/O line that can be measured by the firmware.)\r\n \u003c/li\u003e\r\n\u003cli\u003eCheck the non-volatile register or memory region for a recovery mode cookie value.  If this is set, some later stage of the boot process must have failed and requested recovery mode, so skip to attempt loading recovery firmware.\u003c/li\u003e\r\n \u003cli\u003e\r\n Attempt loading Firmware A.\u003c/li\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003e\r\n Copy Firmware A to RAM.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Verify signature of Firmware A using public key stored in boot stub.\u003c/li\u003e\r\n \u003cli\u003e\r\n If signature is valid, jump to Firmware A Setup.\r\n \u003c/li\u003e\r\n \u003c/ol\u003e\r\n \u003cli\u003e\r\n Firmware A is bad. Repeat for Firmware B.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Both A and B are bad. Attempt loading recovery firmware to RAM and verify signature. If valid, jump to recovery firmware.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n All recovery options have been exhausted. Catch fire / emit POST code / etc.\u003c/li\u003e\r\n \u003c/ol\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Firmware_A_B_Setup_41671303566\" /\u003e\r\n Firmware (A/B) setup\u003c/h3\u003e\r\n\u003cdiv\u003eThis firmware sets up a minimal set of hardware components so that the boot loader can load the kernel from the normal boot drive.  For example, the SATA or eMMC controller.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003ePseudocode\u003c/b\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003eInitialize chipset / file system sufficiently to jump to Boot Loader code.\u003c/li\u003e\r\n \u003cli\u003e\r\n Jump to Boot Loader code.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n \u003c/div\u003e\r\n \u003c/div\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Firmware_A_B_Bootstrap_6854730_9843585162384771\" /\u003e\r\n Firmware (A/B) boot loader\u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n The boot loader is only designed to load Chromium OS. We can go directly from firmware bootstrap to the kernel in the disk.\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cb\u003ePseudocode\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e\r\n\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eVerify the partition table on the disk looks sane.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eLoad kernel A from the disk.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eVerify signature of kernel.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIf signature is invalid:\u003c/span\u003e\u003c/li\u003e\r\n\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIf this is kernel A, retry with kernel B.\u003cbr /\u003e\u003c/span\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eElse this is kernel B.  Both kernels are bad, so set the recovery-mode cookie non-volatile register and reboot into recovery firmware.\u003cbr /\u003e\u003c/span\u003e\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIf kernel was signed with a public key not known to the boot loader, this is a developer kernel:\u003c/span\u003e\u003c/li\u003e\r\n\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eInitialize the display.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eDisplay scary developer mode warning to user. For example: \"Google Chrome OS is not installed.  Press space bar to repair.\"\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eWait for keypress or 30-second delay before continuing.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIf key pressed was Space bar, Enter, or Esc, jump to Recovery Firmware.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIf key pressed was Control+D, dismiss screen.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIgnore other key presses.\u003c/span\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eContinue booting the kernel.\u003c/span\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/b\u003e\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"Boot_Log_909660461358726_02223_241900222824606\" /\u003eBoot log\u003c/h3\u003e\r\n \r\n\u003cdiv\u003eA boot log will be stored at the bottom of the writable section of firmware. This will store the following types of events:\r\n \u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eEach time recovery firmware is run, with information on what triggered it (manual, bad firmware, bad root filesystem, etc.).\u003c/li\u003e\r\n\u003cli\u003eWhen a recovery completes, including which actions were taken.\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003cdiv\u003eIt does not store information on successful boots. This removes the need to support EEPROM writing in the normal boot process, and conserves space for log entries dealing with real errors.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe boot log can be uploaded as part of the autoupdate process. It can then be cleared and reused for new log entries.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Recovery_Firmware_325963526964_9310128691004004\" /\u003e\r\n Recovery firmware\r\n \u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n This firmware attempts to recover from bad firmware or rootfs by loading a recovery image off an external storage device.\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n\u003cb\u003e\r\n Pseudocode\u003c/b\u003e\u003cbr /\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003eWrite a log entry to the boot log indicating why recovery mode was activated (manual, bad writable firmware, user triggers recovery mode, etc.)\u003c/li\u003e\r\n\u003cli\u003e\r\n Initialize enough of the chipset to be able to access a storage device (USB drive, SD card, etc.)\r\n \u003c/li\u003e\r\n \u003cli\u003eCheck for an inserted storage device.  If no storage device is present, skip to displaying recovery instructions.\u003c/li\u003e\r\n\u003cli\u003eVerify the signature of the recovery image, using a public key stored in the recovery firmware.  If the signature is invalid, skip to displaying recovery instructions.\u003c/li\u003e\r\n\u003cli\u003eLoad and run the recovery image.\u003c/li\u003e\r\n\u003cli\u003eIf we're still here, either no storage device was inserted, or the storage device did not contain a valid image.  Display recovery instructions:\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eInitialize the display.\u003c/li\u003e\r\n\u003cli\u003eDisplay instructions.  These instructions must be internationalized and rendered in multiple languages.  The instructions must include:\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cul\u003e\r\n\u003cul\u003e\u003cli\u003eA warning that the computer is in recovery mode\u003c/li\u003e\r\n\u003cli\u003eHow to obtain a trusted recovery image (for example, instructions to go to a second computer and browse to a specified URL for further instructions)\u003c/li\u003e\u003cli\u003eAn indication if an already-inserted storage device does not contain a valid recovery image (sorry, try again).\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cli\u003eWait for a storage device to be inserted, then go back to step 3.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eMost of the recovery work is left to the recovery image loaded from the storage device. This allows for publishing updated recovery images and instructions. Because the recovery firmware is etched in stone (well, as electrons in floating gates) at the time the device is launched, it needs to be as simple and robust as possible.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \r\n\r\n \r\n\u003ch2\u003e\u003ca name\u003d\"Recovery_Image_999069100245833_9862531434570179\" /\u003e\r\n Recovery image\r\n \u003c/h2\u003e\r\n \u003ca name\u003d\"Recovery_Image\" /\u003e\r\n \r\n\u003cdiv\u003e\r\n This is the software loaded onto a storage device (USB drive, SD card, etc.) which does the bulk of the recovery work.\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n\u003cdiv\u003eThe recovery image will be available for download. \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWe will need to provide a downloadable installer for users to use to install the recovery image on the storage device. This installer should be supplied for all popular operating systems (Chromium OS, Windows, Mac OS X, Ubuntu Linux). The installer will:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003ePrompt the user to select a destination for the recovery image\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIdeally, the user will only be able to select destination devices appropriate for recovery of the laptop model they are attempting to recover.\u003c/li\u003e\u003cli\u003eAlso, the user should only be able to select removable devices. We don't want them trashing their hard disk.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eWarn the user that this will erase whatever is on that destination, and prompt for confirmation\u003c/li\u003e\r\n\u003cli\u003eReformat the destination storage device\u003c/li\u003e\r\n\u003cli\u003eInstall the recovery image on the storage device\u003c/li\u003e\r\n\u003cli\u003ePrompt the user to insert the storage device into the Chromium OS device\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003cdiv\u003eIdeally, the installer would be able to back up the current data on the destination device, before reformatting and writing the recovery image. When recovery is complete, the user could re-insert the destination device and have the original contents restored.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe recovery image should contain an entire clean copy of the firmware and rootfs. This way, a user can make a recovery device ahead of time. For example, if a user is going to be somewhere with poor connectivity, they could make a recovery USB drive at home and keep it in their bag. Alternately, the system could come with a recovery device (though users might end up reformatting it and filling it with images of kittens).\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n The recovery image on the storage device would do something like the following:\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003e\r\n Initialize the display and tell the user what's going on. Reassure them that their Chromium OS system is trying to recover.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n If developer firmware is detected, give the user a choice of \"JUST FIX IT\" or \"Scary Settings for L33t H4x0rs\". If the user picks the latter:\r\n \u003c/li\u003e\r\n \r\n\u003col\u003e\r\n \u003cli\u003e\r\n Give the developer more control over each stage in the rest of the recovery. \r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n For example, a developer might not want to wipe and replace rootfs or stateful data, or might want to make a backup of that data.\r\n \u003c/li\u003e\r\n \u003c/ol\u003e\r\n \u003cli\u003e\r\n Run system tests. It's possible that the boot problems are due to bad hardware. Now's the time to detect that.\r\n \u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eIf hardware is sufficiently bad that the rest of recovery can't be run, show the user information on how to return it.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n \u003cli\u003e\r\n Verify both firmware A and firmware B are up-to-date and valid. Load known good firmware as needed.\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Verify rootfs-A and rootfs-B are up-to-date and valid. Load known good rootfs images as needed.\r\n \u003c/li\u003e\r\n \u003cli\u003eWipe the stateful data. Anything the user cares about should be in the cloud anyway. If the user's been hacked, wiping the data will put the device back in a known good state.\r\n \u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eOptionally, it can inform the user that data on the system will be erased.\u003c/li\u003e\r\n\u003cli\u003eThis message should emphasize that most data is saved to the cloud, so that the user is more likely to proceed with recovery.\u003c/li\u003e\r\n\u003cli\u003eIt is less desirable to give the user a choice whether or not to delete the stateful data. Most users would pick the less scary but also less secure option of NOT deleting data - but this leaves them vulnerable to persistent hacks on the data partition, such as manipulating their /etc/hosts file or bookmarks.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003eIf recovery mode was manually triggered, ask the user why they're running it.\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eCouldn't even log in; crash during boot\u003c/li\u003e\r\n\u003cli\u003eKept crashing after boot\u003c/li\u003e\r\n\u003cli\u003eWorried my system was hacked\u003c/li\u003e\r\n\u003cli\u003eHey, what's this button do?\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003eWrite an entry to the boot log describing repairs performed.\u003c/li\u003e\r\n \u003c/ol\u003e\r\n \u003c/div\u003e\r\n \r\n\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Recovery_via_Chrome_OS_2183209_6000941713093587\" /\u003eRecovery via Chromium OS\u003c/h3\u003e\r\n\u003cdiv\u003eThe recovery installer should run on a healthy Chromium OS system. That is, it should be able to download the recovery image, reformat the storage device, and copy the recovery image to it. \u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eThis enables a healthy Chromium OS system to create its own recovery device in advance. \u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003ePerhaps we should periodically advise users to update their recovery device?\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eIt also enables one Chromium OS system to download a recovery image for a different model. (A user has a corrupt system, so they go to their friend's house and use the friend's Chromium OS system to make a recovery image).\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n \r\n\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Making_Recovery_Images_Read_On\" /\u003e\r\n Making recovery images read-only\r\n \u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n If the recovery image is inserted into a powered-on and hacked system, the hacked software could delete or corrupt it. This won't cause the recovery firmware to load that corrupt image, because the corrupt image will fail the signature check. It will be annoying to the user, who will need to reflash the storage device.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n This is more of an issue if we want to include an internal recovery image (for example, on an internal storage device).\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n The SD standard specifies a physical write-protect notch for SD cards, similar to those on a 3.5\" floppy disk. Unfortunately, the implementation of the write-protection is purely software, so pwned drivers can choose to ignore the write-protect detect signal.\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \u003c/div\u003e\r\n \u003c/div\u003e\r\n \u003c/div\u003e\r\n Some USB drives have a write-protect switch on them. In this case, the protection is handled by the USB drive itself.\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n Some eMMC chips have a number of protection mechanisms including:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n an external LOCK# pin which can be used to make the device read-only\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n a write-once bit which makes the device read-only until reboot\r\n \u003c/li\u003e\r\n \u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n Since these chips come in sizes up to 2GB (~$10 at stores), they provide a possible place to store a recovery image. Some system architectures may be able to use the eMMC drive to hold the main firmware image also.\u003cbr /\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n If we have an internal storage device, it's possible we could wire it so it's only enabled if the recovery button is pressed at boot time. For example, we could use that button to latch up a circuit which powers that device, so that it will remain powered during that boot only.\r\n \u003c/div\u003e\r\n \r\n\r\n\u003ch3\u003e\u003ca name\u003d\"Using_Recovery_Mode_to_load_De\" /\u003eUsing recovery mode to load developer mode firmware/software\u003c/h3\u003e\r\n\u003cdiv\u003eIf the rootfs image on the SD card is signed by someone else, the recovery image will display a screen similar to the Developer Mode screen.  Instructions on this screen should include:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eNotice that the recovery image is signed by someone else\u003c/li\u003e\r\n\u003cli\u003eHow to obtain a trusted recovery mode image\u003c/li\u003e\r\n\u003cli\u003eInstructions on installing a trusted recovery image\u003c/li\u003e\r\n\u003cli\u003eA means of allowing the user/developer to proceed down the \"untrusted\" path\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003eNote that this screen must also be internationalized / rendered in multiple languages. This is potentially much easier, since by the time we're doing this the recovery image has booted a full OS with GUI.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"Boot_Flowchart_033826657570898\" /\u003eBoot flowchart\u003c/h2\u003e\r\n\u003cdiv\u003eThe three main downward flows in this chart show:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eStart of boot in read-only firmware\u003c/li\u003e\r\n\u003cli\u003eNormal continuation of boot, loading kernel from internal drive\u003c/li\u003e\r\n\u003cli\u003eRecovery mode\u003c/li\u003e\u003c/ul\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery/ChromeOSFirmwareBootandRecoveryPUBLISHED.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1277241373652/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery/ChromeOSFirmwareBootandRecoveryPUBLISHED.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\" /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Other-notes\" /\u003eOther notes\u003c/h2\u003e\r\n\u003c/div\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"Verification_of_the_Rest_of_ro\" /\u003e\r\n Verification of the rest of the rootfs\r\n \u003c/h3\u003e\r\n \r\n\u003cdiv\u003e\r\n The firmware boot process above describes a way to verify all code from the start of boot through hand off to the kernel. \r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n \u003cbr /\u003e\r\n \u003c/div\u003e\r\n \r\n\u003cdiv\u003e\r\n The kernel is responsible for verifying the rest of the data in the rootfs - for example, user-mode drivers. If the kernel determines that the rootfs has been compromised, it can force recovery mode to run by setting the recovery mode cookie in a non-volatile register and rebooting into recovery mode.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eAlternately, a kernel which determines its rootfs is corrupt can commit suicide by marking its partition as inactive and then rebooting. The next boot will do one of the following:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eIf the other root partition is good, the boot loader will run the other root partition.\u003c/li\u003e\r\n\u003cli\u003eIf neither root partition is good, the boot loader will trigger the recovery mode firmware, which can put the rootfs back in a known state.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n \r\n\r\n \r\n\u003cdiv\u003e\r\n \r\n\u003ch3\u003e\u003ca name\u003d\"When_to_Verify_the_Boot_Proces\" /\u003e\r\n When to verify the boot process\r\n \u003c/h3\u003e\r\n \r\n\u003cdiv\u003eWe should develop under the initial assumption that we can verify every boot, since this provides the most security. \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSignature-checking code does impact startup time. However, this is likely not an issue for the firmware (\u0026lt; 1 MB) and kernel (\u0026lt; 10 MB) than it is for the remainder of the rootfs. We assume that we will verify the entire firmware and kernel every boot.\u003c/div\u003e\r\n \r\n\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"Handling_Returned_Netbooks_578\" /\u003eHandling returned systems\u003c/h3\u003e\r\nWhen a Chromium OS system is returned to the store, the store should check to make sure it still boots.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eIf it boots normally, the store can follow their standard process for dealing with returns.\u003c/li\u003e\r\n\u003cli\u003eIf it displays the Scary Dev Mode screen, the store can either run recovery mode or refuse the return (in which case the original owner can go home and run recovery mode, then come back and returns the system again).\u003c/li\u003e\r\n\u003cli\u003eIf it fails to boot, it gets shipped back to the manufacturer.\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003cdiv\u003eNote that it's advisable for stores to run recovery mode on returned computers anyway, to put them back into a clean state and destroy any user data still on the device.\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"Testing_17694905913316072_043226863012933325\" /\u003eTesting\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe comprehensive test suite for Chromium OS should include tests of each stage of the verification process and the recovery procedure, including all decision points in the pseudocode/flowchart. This will require actual hardware for each firmware image being tested.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eTesting should also attempt to write to the read-only portion of the EEPROM, to ensure that it is in fact not writable.\u003c/div\u003e\r\n\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"Open_Issues_6727640628814697_9\" /\u003eOpen issues\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"What_Else_Do_We_Need_To_Verify\" /\u003e\r\n What else do we need to verify?\r\n\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n This document describes verifying the following:\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n Firmware in the main EEPROM\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n Partition table\r\n \u003c/li\u003e\u003cli\u003eThe kernel partition\u003c/li\u003e\r\n \u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n It explicitly does not discuss verifying:\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n The rootfs (anything after the hand off to the kernel)\r\n \u003c/li\u003e\r\n \u003cli\u003eThe stateful data partition\u003c/li\u003e\r\n \u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n Are there other locations for persistent storage we should be verifying? For example:\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n Firmware in other components?\r\n \u003c/li\u003e\r\n \r\n\u003cul\u003e\r\n \u003cli\u003e\r\n File system\u003c/li\u003e\r\n \u003cli\u003e\r\n NIC\r\n \u003c/li\u003e\r\n \u003cli\u003e\r\n 3G modem\r\n \u003c/li\u003e\r\n\u003cli\u003eEmbedded controller\u003c/li\u003e\r\n\u003cli\u003eModem processor (on ARM systems)\u003c/li\u003e\r\n \u003cli\u003e\r\n Keyboard (\u003ca href\u003d\"http://www.engadget.com/2009/08/04/apple-keyboard-gets-hacked-like-a-ripe-papaya-perp-caught-on-vi\" target\u003d\"_blank\" title\u003d\"this apparently is an attack surface on some systems\" rel\u003d\"nofollow\"\u003ethis apparently is an attack surface on some systems\u003c/a\u003e)\r\n \u003c/li\u003e\r\n\u003cli\u003e(we disallow option ROMs in the hardware spec, so we don't need to worry about those)\u003c/li\u003e\r\n \u003c/ul\u003e\r\n \u003cli\u003eRemovable user media\u003c/li\u003e\r\n \u003c/ul\u003e\r\n\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"Can_we_log_firmware_crashes_54_8565273169739532\" /\u003eCan we log firmware crashes? \u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eCrashes in boot stub (i.e., north bridge / RAM init) likely aren't loggable at all. Not enough of the system is running.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eOther crashes in the firmware could write a cookie into a particular address in SDRAM. \u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWhen the system boots next, it could check that address for a valid crash cookie. \u003c/li\u003e\r\n\u003cli\u003eIf so, assume the current firmware is bad; try the backup firmware, or go to recovery mode.\u003c/li\u003e\r\n\u003cli\u003eDownside: Intermittent crashes which would be mildly annoying now prevent the system from attempting to boot at all, since it would tend to go into recovery mode.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eCrashes in the kernel can be logged to the stateful partition.\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"Chain_of_verification_on_ARM_2_45279574090983055\" /\u003eChain of verification on ARM?\u003c/h3\u003e\r\n\u003cdiv\u003eSome ARM SOCs contain a modem processor and an application processor. On boot, only the modem processor is running; its firmware then sets up and starts the application processor. If the modem firmware is writable, we could be hacked before the first instruction of our firmware executes. We need a way to secure the modem firmware. (This is true regardless of the boot order, if the modem firmware has access to the registers or RAM used by the application processor). \u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSuch systems could use a Memory Protection Unit or similar such hardware solution, to prevent the modem and application processors from reading/writing each other's firmware or memory space, except for specific portions of the memory space used for inter-processor communication. We are still investigating what solutions can be used for verified boot.\u003c/div\u003e\r\n\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"Support_for_Trusted_Platform_M_472807140635382\" /\u003eSupport for Trusted Platform Module (TPM)?\u003c/h3\u003e\r\n\u003cdiv\u003eA TPM is not required for key verification for the firmware boot and recovery process described in this document. There's no point in the verification key being more secure than the code in ROM used to do the verification.  If an attacker can crack the ROM code, they can just make it bypass the TPM check.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nIf the boot stub contains a secondary key which is date-limited, it is desirable to use the TPM to verify the date-limited key is valid. Many TPM modules contain their own clock/counter, so can be used to defend against turn-back-the-clock attacks.  Similarly, if we use numbered or sequential secondary keys, storing the highest-seen key number in the TPM can protect against rollback attacks.\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003cdiv\u003eThere may be some firmware requirements to set up the TPM so that subsequent activities (3G authentication, etc.) can get access to the keys stored in the TPM.\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4723945718499501890"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4723945718499501890"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4723945718499501890"}],"author":[{}],"sites$pageName":{"$t":"firmware-boot-and-recovery"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8565171045834459738"},"published":{"$t":"2015-04-23T22:40:20.420Z"},"updated":{"$t":"2015-04-23T23:02:14.084Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-23T23:02:12.883Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"No Hidden Preferences"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eOne of the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/core-principles\"\u003eCore Principles\u003c/a\u003e is Simplicity:\u003cdiv\u003e\u003cbr /\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003eWe tend to avoid complex configuration steps in every aspect of the product, from installation through options. We take care of keeping the software up to date so you never need to be concerned about running the latest, safest version of Chrome.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003eWe try not to interrupt users with questions they are not prepared to answer, or get in their way with cumbersome modal dialog boxes that they didn't ask for.\u003c/div\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe target user base for Chromium is incredibly diverse, and while we try to make Chromium flexible and powerful enough to serve everyone well, the reality is that we can't always do that. Some users might want different behaviors, and the easy way out is to give them that option. That is a temptation that must be resisted.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen we make a hidden preference, it is admitting failure. If our users complain about a feature, do we add a preference for it to be turned off? If we do so we're ignoring the feedback of our users that perhaps the feature could be smarter in satisfying their needs. In addition, as software developers we usually don't think about it, but setting a preference is a pretty technically complicated task, so adding one wouldn't actually help the vast majority of the users, who will end up suffering with the feature in silence. Take the feedback to improve the feature, not to add a switch to turn it off.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eHidden settings also make it nearly impossible to do full testing. Each boolean-valued preference means that the code can behave one of two ways. Do you write all your tests to take those two branches into account? Each additional preference means twice the number of code paths, meaning exponential growth. This means preferences are bad for maintainability.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003eabout:flags and command-line flags are only for temporary testing. L\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eong-lived command-line flags are prohibited except for rare cases \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ewhere we need them for long-term testing and development.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRecommended external links:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://ignorethecode.net/blog/2008/05/18/preferences-considered-harmful/\" rel\u003d\"nofollow\"\u003eignore the code: Preferences Considered Harmful\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://www.joelonsoftware.com/uibook/chapters/fog0000000059.html\" rel\u003d\"nofollow\"\u003eJoel Spolsky: Choices\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/218080671730941543"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/core-principles/no-hidden-preferences"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8565171045834459738"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8565171045834459738"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8565171045834459738"}],"author":[{"name":{"$t":"Avi Drissman"},"email":{"$t":"avi@chromium.org"}}],"sites$pageName":{"$t":"no-hidden-preferences"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"Wyl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/218080671730941543"},"published":{"$t":"2009-08-07T00:16:55.788Z"},"updated":{"$t":"2015-04-23T22:39:34.724Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-09-18T21:49:31.928Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Core Principles"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eThese are the things that are important to us: these principles shape the product that we build. Note that the examples given are meant to be illustrative rather than exhaustive.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:medium\"\u003eSpeed\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOur objective is to make the fastest browser - and we tackle this in a number of ways.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eBecause the speed of rich web applications is important to us, we develop our own JavaScript engine, called V8.\u003c/li\u003e\u003cli\u003eBecause the speed of page display is important to us, we develop our own rendering engine, called Blink. It's incredibly fast.\u003c/li\u003e\u003cli\u003eWe pay attention to the speed of user interactions - from starting the browser to common actions like opening new tabs and windows, and switching between them. Noticeable lags are not acceptable.\u003c/li\u003e\u003cli\u003eWe develop and pay close attention to automated tests for all of these things, and run them in combination with new features we develop so that we can be sure we're always getting better, not worse.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eWhen preparing changelists, we ask ourselves questions like:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Does my code make Chrome slower? If it does, how do I fix it?\"\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I created automated performance testing for my feature? Have I created variations of existing performance tests to measure performance with my feature enabled?\"\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"What opportunities are there for better performance in my feature? Have I filed bugs and labeled them with the Performance label?\"\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;font-style:normal;border-collapse:collapse\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-style:italic\"\u003e\"How will my code perform when the operating system or hard disk is bogged down?\"\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-style:italic\"\u003e\"Am I taking care to avoid \"blocking file system access\" on the UI and IO threads?\"\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAsk yourself these questions before you commit your code. If you make a change that regresses measured performance, you will be required to fix it or revert. There are many tools available to help isolate bottlenecks. (LINK to tuning doc).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:medium\"\u003e\u003cb\u003eSecurity\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs users spend more time in the browser and do more sensitive activities there (banking, tax returns, email) it is increasingly important that we provide the most secure environment that we can for our users.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe operate with the principle of least privilege. To the extent possible, code is sandboxed and its privileges to interact with the host system are restricted as tightly as possible. Untrusted (web) content is intended to never be handled in privileged code, but instead passed off to sandboxed code for consumption.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe believe in defense in depth. We have protections for our users at multiple levels. While the sandbox is designed to make sure that malware cannot install itself onto and read data from your system, we have other components such as Safe Browsing to help prevent users from reaching malware in the first place.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe believe that security must be usable. Showing the user a certificate's fingerprint and throwing up our arms asking \"what shall we do?\" is not solving the problem at hand. Instead, we strive to provide a more understandable context in which relevant information (if any) is presented, along with explanations, encouraging users to take a safe default action.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe believe that users should be safe by default. We should not expect users to take actions to be secure, rather we should act given the information we have to keep the user secure. We automatically update users to the latest version, we set reasonable defaults for security-related features, and we understand that users are focused on a task, not on security, and act accordingly.\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:medium\"\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:medium\"\u003eStability\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eBecause browsers are more than just content viewers these days, we do a lot more in them. It's important that they act more like platforms.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe apply conventional thinking in operating system design to the web browser. A bug that affects one application should not bring all of them down. With that in mind, we separate individual tabs into their own processes. We also do this for plugins.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe try to write as many automated tests as we can, to make sure that the product is still functioning as intended. We close the tree when the tests fail. We revert changes that break them. We seek to improve our code coverage in such tests over time.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe work to get a good sense of the stability of any build before we push it to our users. We gather data in a couple of ways, such as crash dumps from people who have opted in to sending them, and our own farm of automated test machines that run many builds a day against Google's cache of various web sites. We use the crash stats to determine how we should prioritize engineering work, and avoid shipping particularly crashy builds to stabler channels.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen writing code, and before sending a changelist for review, we ask ourselves questions like:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"How can I write my code to maximize code coverage from unit tests?\" ... unit tests are typically less flaky and easier to debug than UI tests.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I written or updated unit tests for the code I've changed?\" ... all non-trivial changes should have a unit test -- the more coverage we can get from them, the more confident we can be in the stability of a release.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I run valgrind while exercising my feature and its tests?\"\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I isolated potentially brittle/untrusted code parsing in a utility process?\" ... for example, web pages, profile migration, theme PNG decoding, extension parsing, etc. are all done in child processes.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I hidden my unfinished experimental feature behind a command line flag so as not to destabilize the weekly dev channel?\"\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:medium\"\u003eSimplicity\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eGoogle is all about incredibly sophisticated technology, but wrapped in a simple user experience. We do everything we can to optimize user interactions. The foremost way in which we've done this is by removing distractions from the browser itself, and letting page content speak for itself. \"Content, not Chrome\" is our mantra.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe tend to avoid complex configuration steps in every aspect of the product, from installation through options. We take care of keeping the software up to date so you never need to be concerned about running the latest, safest version of Chrome.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe try not to interrupt users with questions they are not prepared to answer, or get in their way with cumbersome modal dialog boxes that they didn't ask for.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe take hints from our host platform, but retain a distinctive aesthetic.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe want the browser to feel like a natural extension of your will. It should feel fluid and delightful. It's about getting you to the information you need, not about driving a piece of software.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen writing code and designing features, we ask questions like:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I talked to UI design group (chrome-ui-leads at google dot com) about my change?\"\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I made sure all non-trivial work is done off the UI thread, so the UI is never unresponsive for \u0026gt; 200ms?\" - UI jank is the devil. Don't make your change contribute to it.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I done my best to avoid introducing unexpected modal workflows, popups, questions the user can't answer, superfluous extra options?\" - we bend over backwards to avoid these things.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\"Have I spent time before the next major release polishing my feature, making sure it has all appropriate animations, plays nicely with other Chrome features like themes, etc?\" - UI polish is important to us. We want to make sure the UI looks and feels tight. Think of the interior trim pieces on an expensive car.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/core-principles"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/218080671730941543"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/218080671730941543"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/218080671730941543"}],"author":[{"name":{"$t":"Ben Goodger"},"email":{"$t":"ben@chromium.org"}}],"sites$pageName":{"$t":"core-principles"},"sites$revision":{"$t":"22"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2492593016229861619"},"published":{"$t":"2014-08-23T19:05:41.014Z"},"updated":{"$t":"2015-04-23T00:22:30.949Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-23T00:22:29.716Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Working with your Overlay FAQ"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:12pt;margin-bottom:2pt\"\u003e\u003ca name\u003d\"TOC-Basics-Workflow\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBasics / Workflow\u003c/span\u003e\u003c/h2\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:12pt;margin-bottom:2pt\"\u003e\u003ca name\u003d\"TOC-What-is-a-board-What-is-an-overlay-What-is-an-ebuild-What-is-a-bsp-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhat is a board? What is an overlay? What is an ebuild? What is a bsp?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBasic \u003c/span\u003e\u003ca href\u003d\"https://docs.google.com/document/d/16PWfmUkv5ZRoeaJeggHqF8cNwgSPLeL2I_D7UKubV4w/pub\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eterms and concepts\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:12pt;margin-bottom:2pt\"\u003e\u003ca name\u003d\"TOC-I-made-changes-to-my-board-s-bsp-but-build_packages-build_image-didn-t-pick-them-up.\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eI made changes to my board's bsp but build_packages/build_image didn't pick them up.\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAfter you make a change to the bsp, you need to either \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/portage-build-faq#TOC-How-do-I-uprev-an-ebuild-\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003euprev\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e or re-emerge it for build_packages/build_image to pick up the changes. (We realize this isn't ideal: See \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/391962\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ehttp://crbug.com/391962\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-How-do-I-push-changes-that-I-made-to-my-app-to-my-developer-device-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow do I push changes that I made to my app to my developer device?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eUse \u003c/span\u003e\u003ca href\u003d\"http://dev.chromium.org/chromium-os/build/cros-deploy\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ecros deploy\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Packages\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ePackages\u003c/span\u003e\u003c/h2\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-My-app-depends-and-uses-a-third-party-library.-How-do-I-tell-the-build-system-to-do-that-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMy app depends and uses a third party library. How do I tell the build system to do that?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFirst, check if the third party library is already available as a Gentoo package under \u003c/span\u003e\u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/portage-stable/+/master/\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esrc/third_party/portage-stable\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e or \u003c/span\u003e\u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esrc/third_party/chromiumos-overlay\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. \u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIf yes, then just add the package name to the DEPEND (if build-time dependency) and/or RDEPEND (if run-time dependency) of your app's ebuild.\u003c/span\u003e\u003c/p\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:12pt;margin-bottom:2pt\"\u003e\u003ca name\u003d\"TOC-How-do-I-add-additional-packages-to-my-target-board-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow do I add additional packages to my target \u0026lt;board\u0026gt;?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAdd it as an RDEPEND to chromeos-base/chromeos-bsp/chromeos-bsp-\u0026lt;board\u0026gt;.ebuild in your overlay.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eExample \u003c/span\u003e\u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/3c9d9f7a1e35861586cf39218d796e1f29869ad8/overlay-gizmo/chromeos-base/chromeos-bsp-gizmo/chromeos-bsp-gizmo-0.0.1.ebuild\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBSP\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e that pulls in peerd and bash on the target.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:12pt;margin-bottom:2pt\"\u003e\u003ca name\u003d\"TOC-Startup-Boot\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eStartup / Boot \u003c/span\u003e\u003c/h2\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:12pt;margin-bottom:2pt\"\u003e\u003ca name\u003d\"TOC-How-do-I-make-my-program-service-automatically-start-on-boot-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow do I make my program/service automatically start on boot?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCrOS uses the \u003c/span\u003e\u003ca href\u003d\"http://upstart.ubuntu.com/cookbook/\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eupstart\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e system to manage boot and service startup. Simply add an upstart job for your service and install it into \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e/etc/init\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eExample upstart script: \u003c/span\u003e\u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/3c9d9f7a1e35861586cf39218d796e1f29869ad8/overlay-variant-panther-embedded/chromeos-base/chromeos-bsp-panther-embedded/files/load-network-drivers.conf\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003elink\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Should-my-upstart-job-depend-upon-boot-services-or-system-services-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eShould my upstart job depend upon boot-services or system-services?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esystem-services, unless your job in the critical boot path (e.g. network driver setup), in which case boot-services is appropriate.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe following additional resources go into more detail:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"http://dev.chromium.org/chromium-os/boot-milestones\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMore information\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/userland-boot\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBoot system design\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/working-with-your-overlay-faq"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2492593016229861619"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2492593016229861619"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2492593016229861619"}],"author":[{"email":{"$t":"gauravsh@chromium.org"}}],"sites$pageName":{"$t":"working-with-your-overlay-faq"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},"published":{"$t":"2015-04-09T06:56:31.423Z"},"updated":{"$t":"2015-04-20T22:38:44.761Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T16:53:06.247Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Lenovo Chromebook N20 \u0026 N20P"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"https://www.google.com/chromebook/\"\u003eLenovo Chromebook N20 \u0026amp; N20P\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\u003cp\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562874869/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-1-hinge.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562879516/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-2-front.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562883931/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-3-left.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562888979/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-4-right.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562893508/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-5-hinge.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562896001/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-6-side-left.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428562910783/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-7-side-right.jpg\" width\u003d\"200\" /\u003e\r\n\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eWeight: 2.87 lbs\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eCPU: Baytrail Intel Celeron Dual-Core \u003ca href\u003d\"http://ark.intel.com/products/81071/Intel-Celeron-Processor-N2830-1M-Cache-up-to-2_41-GHz\" rel\u003d\"nofollow\"\u003eN2830\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GiB DDR3 (Not upgradeable)\u003c/li\u003e\r\n\u003cli\u003eDisplay: 11\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e.6\" \u003c/span\u003e1366x768\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eDisk: 16GB SSD\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eI/O:\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI miniport\u003c/li\u003e\r\n\u003cli\u003e1 x USB 2.0\u003c/li\u003e\r\n\u003cli\u003e1 x USB 3.0\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\r\n\u003cli\u003eCamera \u0026amp; mic\u003c/li\u003e\r\n\u003cli\u003eKeyboard \u0026amp; touchpad\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n/ac\u003c/li\u003e\r\n\u003cli\u003eBluetooth 4.0\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eUSB ports can handle some Ethernet dongles\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eno \u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eLinux 3.10\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eDetails for working with developer mode can be found \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook\"\u003eon this page\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-clapper-5216.199.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-clapper-5216.199.B \u003c/code\u003e branch.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process. Really, just don't.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your Chromebook is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center. There's nothing inside that you can fix yourself. Be advised that disassembly might \u003cb\u003evoid warranties\u003c/b\u003e or other obligations, so please consult any and all paperwork you received first.\u003c/p\u003e\r\n\r\n\u003cp\u003eFine. If you \u003cb\u003emust\u003c/b\u003e risk breaking it for good, at least do it the right way.\u003c/p\u003e\r\n\u003cul\u003e\r\n\u003cli\u003eNote: Lenovo provides \u003ca href\u003d\"http://download.lenovo.com/consumer/mobiles_pub/lenovo_n20p_chromebook_hmm.pdf\" rel\u003d\"nofollow\"\u003edocumentation\u003c/a\u003e for disassembling the device. Please follow that first. These directions are a simple fallback.\u003c/li\u003e\u003cli\u003eFirst, acquire the necessary tools:\u003c/li\u003e\u003cul\u003e\u003cli\u003eA small Phillips head screw driver\u003c/li\u003e\u003cli\u003eA \u003ca href\u003d\"http://en.wikipedia.org/wiki/Spudger\" rel\u003d\"nofollow\"\u003espudger\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eClose the laptop and flip it over so the bottom is facing up\u003c/li\u003e\u003cul\u003e\u003cli\u003eRemove the 8 screws (two are under the rubber feet near the hinge)\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eFlip the laptop over and open it so the keyboard is facing up\u003c/li\u003e\u003cul\u003e\u003cli\u003ePower it off if it powers on\u003c/li\u003e\u003cli\u003eUsing the spudger, pry the laptop off starting from the top edge\u003c/li\u003e\u003cli\u003eIt uses sticky glue in the middle area, so it might be a little difficult\u003c/li\u003e\u003cli\u003eTry to pull it down uniformly to minimize chances of breaking\u003c/li\u003e\u003cli\u003eDetach the keyboard \u0026amp; touchpad cables\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eRemove the 9 screws that were under the keyboard\u003c/li\u003e\u003cul\u003e\u003cli\u003eUse the spudger to remove the upper half of the case and expose the motherboard\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/839736656483527454"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"lenovo-chromebook-n20"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2654826488700771638"},"published":{"$t":"2014-10-03T00:01:02.245Z"},"updated":{"$t":"2015-04-20T22:38:38.735Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-20T22:38:36.476Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"HP Chromebox"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eEntering\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-USB-Boot\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eUSB Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eLegacy Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eLeaving\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Troubleshooting\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eTroubleshooting\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot-Doesn-t-Work\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eLegacy Boot Doesn't Work\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Running-Chromium-OS\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eRunning Chromium OS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the HP Chromebox that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eCPU: Haswell Celeron 2995U. 1.4GHz, dual-core, 2MB Cache OR 1.7 GHz Core i3-4010U, quad-core\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GB (celeron) or 4GB (i7)\u003c/li\u003e\r\n\u003cli\u003eDisplay: None\u003c/li\u003e\r\n\u003cli\u003eDisk: 16GB SSD (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Next_Generation_Form_Factor\" rel\u003d\"nofollow\"\u003eNGFF\u003c/a\u003e M.2 connector)\u003c/li\u003e\r\n\u003cli\u003eI/O:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI port\u003c/li\u003e\r\n\u003cli\u003eDisplayPort++\u003c/li\u003e\r\n\u003cli\u003e4 x USB 3.0\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n\u003c/li\u003e\r\n\u003cli\u003eUSB ports can handle some Ethernet dongles\u003c/li\u003e\r\n\u003cli\u003eEthernet\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eServo header\u003c/a\u003e: Standard 2x25 / AXK750347G\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eIntroduction\u003c/font\u003e\u003c/b\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003cp\u003eEnabling Developer mode is the first step to tinkering with your Chromebox. With Developer mode enabled you can do things like poke around on a command shell (as root if you want), install Chromium OS, or try other OS's. Note that Developer mode turns off some security features like verified boot and disabling the shell access. If you want to browse in a safer, more secure way, leave Developer mode turned OFF. Note: Switching between Developer and Normal (non-developer) modes will remove user accounts and their associated information from your Chromebox.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Entering\" /\u003eEntering\u003c/h3\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eTo invoke Recovery mode, you insert a paper clip and press the \u003cfont color\u003d\"#990000\"\u003eRECOVERY\u003c/font\u003e\u003cfont color\u003d\"#e06666\"\u003e \u003c/font\u003e\u003cfont color\u003d\"#990000\"\u003eBUTTON \u003c/font\u003e(just above the kensington lock) and\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e press the\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e \u003c/span\u003e\u003cfont color\u003d\"#990000\" style\u003d\"font-size:10pt;background-color:transparent\"\u003ePower\u003c/font\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ebutton. Release the \u003cfont color\u003d\"#990000\"\u003eRECOVERY BUTTON\u003c/font\u003e after a second.\u003c/span\u003e\u003c/p\u003e\r\n\u003cp\u003eTo enter Dev-mode you first invoke Recovery, and at the Recovery screen press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e (there's no prompt - you have to know to do it). It will ask you to confirm by pressing the \u003cfont color\u003d\"#990000\"\u003eRECOVERY BUTTON\u003c/font\u003e again.\u003c/p\u003e\r\n\u003cp\u003eDev-mode works the same as always: It will show the scary boot screen and you need to press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e or wait 30 seconds to continue booting.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-USB-Boot\" /\u003eUSB Boot\u003c/h3\u003e\r\n\u003cp\u003eBy default, USB booting is disabled. Once you are in Dev-mode and have a root shell, you can run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo crossystem dev_boot_usb\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot from USB drives with Ctrl-U.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot\" /\u003eLegacy Boot\u003c/h3\u003e\r\n\u003cp\u003eThis device includes the SeaBIOS firmware which supports booting images directly like a legacy BIOS would. Note: the BIOS does not provide a fancy GUI for you, nor is it easy to use for beginners. You will need to manually boot/install your alternative system.\u003c/p\u003e\r\n\u003cp\u003eLike USB boot, support for this is disabled by default. You need to get into Dev-mode first and then run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo crossystem dev_boot_legacy\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot legacy images with \u003cfont color\u003d\"#990000\"\u003eCtrl-L.\u003c/font\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Leaving\" /\u003eLeaving\u003c/h3\u003e\r\n\u003cp\u003eTo leave Dev-mode and go back to normal mode, just follow the instructions at the scary boot screen. It will prompt you to confirm.\u003c/p\u003e\r\n\u003cp\u003eIf you want to leave Dev-mode programmatically, you can run \u003ccode\u003ecrossystem disable_dev_request\u003d1; reboot\u003c/code\u003e from a root shell. There's no way to enter Dev-mode programmatically, and just seeing the Recovery screen isn't enough - you have to use the three-finger salute which hard-resets the machine first. That's to prevent a remote attacker from tricking your machine into dev-mode without your knowledge.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Troubleshooting\" /\u003eTroubleshooting\u003c/h2\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot-Doesn-t-Work\" /\u003eLegacy Boot Doesn't Work\u003c/h3\u003e\r\n\u003cp\u003eSometimes it's possible to break the SeaBIOS install in the flash (sometimes doing innocuous things like tweaking the GBB flags). If you do get into such a situation:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eCheck that dev_boot_legacy is set to 1 when you run crossystem\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIf it isn't, then see the normal Legacy Boot section above\u003c/li\u003e\r\n\u003cli\u003eif it is, then see below\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cp\u003eYou can safely reset the copy of SeaBIOS in your flash by running (as root):\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e# chromeos-firmwareupdate --sb_extract /tmp\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e# flashrom -w /tmp/bios.bin -i RW_LEGACY\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Running-Chromium-OS\" /\u003eRunning Chromium OS\u003c/h2\u003e\r\n\u003cp\u003eBefore you start fiddling with your own builds it is strongly recommend to create a recovery USB stick or SD card. As long as you don't disable hardware write protect on the system \u0026amp; EC firmware, you can get your machine back into working order by entering Recovery Mode and plugging in your recovery image. You can create a recovery image from Chrome OS by browsing to \u003ca style\u003d\"color:rgb(71,18,100)\"\u003echrome://imageburner\u003c/a\u003e or follow instructions for other OS on the \u003ca href\u003d\"https://support.google.com/chromebook/answer/1080595?hl\u003den\"\u003eChrome OS help center\u003c/a\u003e site.\u003c/p\u003e\r\n\u003cp\u003eYou can build and run Chromium OS on your HP Chromebox (versions R32 and later). Follow the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/quick-start-guide\"\u003equick start guide\u003c/a\u003e to setup a build environment. The board name for the HP Chromebox is \"zako\". Build an image and write it to a USB stick or SD card.\u003c/p\u003e\r\n\u003cp\u003eTo boot your image you will first need to enable booting developer signed images from USB (or SD card). Switch your machine to Developer mode and get to a shell by either via VT2 (Ctrl+Alt+F2) and logging in as root or by logging in as a user (or guest mode), starting a \"crosh\" shell with Ctrl+Alt+t, and typing \"shell\". Now run \"sudo crossystem dev_boot_usb\u003d1\" and reboot \"sudo reboot\".\u003c/p\u003e\r\n\u003cp\u003ePlug your USB stick or SD card in and on the scary \"OS Verification is OFF\" screen hit Ctrl+u to boot from external media. If all goes well you should see a \"Chromium OS\" logo screen. If you want to install your build to the SSD, open a shell and type \"sudo /usr/sbin/chromeos-install\". Note: This will replace EVERYTHING on your SSD. Use a recovery image if you want to get back to a stock Chrome OS build.\u003c/p\u003e\r\n\u003cp\u003eHave fun!\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e and \u003ca href\u003d\"http://www.denx.de/wiki/U-Boot\" rel\u003d\"nofollow\"\u003eDas U-Boot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-panther-4920.24.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e and the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/u-boot/+/firmware-panther-4920.24.B\"\u003eChromium OS u-boot git tree\u003c/a\u003e in the\u003ccode\u003efirmware-zako-5219.B\u003c/code\u003e branches.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebox"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2654826488700771638"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2654826488700771638"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2654826488700771638"}],"author":[{"name":{"$t":"Jean Zheng"},"email":{"$t":"jean@chromium.org"}}],"sites$pageName":{"$t":"hp-chromebox"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6176481638539759221"},"published":{"$t":"2008-11-05T20:12:57.601Z"},"updated":{"$t":"2015-04-20T17:53:56.893Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-20T17:53:55.398Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Mach based OS X Interprocess Communication (Obsolete)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"text-align:right\"\u003e\u003cdiv style\u003d\"text-align:center\"\u003e\r\n \r\n \u003ch2\u003e\u003ca name\u003d\"TOC-Mach-based-IPC-Design\" /\u003e\u003cu\u003e\u003cfont size\u003d\"5\"\u003eMach based IPC Design\u003c/font\u003e\u003c/u\u003e\u003cbr /\u003e\u003c/h2\u003e\r\n \r\n \r\n \u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cu\u003eCurrent status of this design:\u003c/u\u003e\u003cbr /\u003eThe design described here is currently not used on OS X.  Please see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/inter-process-communication\"\u003eInterprocess Communication\u003c/a\u003e design doc for coverage of the current implementation for all platforms.\u003cbr /\u003e\u003cbr /\u003eA reference implementation of Mach based IPC including a kqueue bridge can be found in \u003ca href\u003d\"http://code.google.com/p/chromium/issues/detail?id\u003d5308\" target\u003d\"_blank\"\u003eissue 5308\u003c/a\u003e.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn 2015, another consideration was given to using Mach IPC, and \u003ca href\u003d\"https://docs.google.com/a/chromium.org/document/d/14-twSrkEhgPI87Pi757auoRhzFYRPqbzdHorHhJn0Kk/edit#\"\u003ethe results of that survey are here\u003c/a\u003e.\u003cbr /\u003e\u003cbr /\u003e\u003cu\u003eRationale for not using Mach based IPC:\u003c/u\u003e\u003cbr /\u003eChrome handles network communication and IPC messages on the same thread.  Sockets are waited on using kqueues via libevent.\u003cbr /\u003eAlthough there is a constant defined in the kqueue headers on OS X (\u003cspan style\u003d\"font-family:courier new,monospace\"\u003eEVFILTER_MACH\u003c/span\u003e in \u003cspan style\u003d\"font-family:courier new,monospace\"\u003esys/event.h\u003c/span\u003e), there is currently no way to block on both a socket and a mach port at once, this means that our only option is to spawn another thread to bridge Mach messages to kqueue.  Our reference implementation does this by opening a pipe between both threads and writing a byte each time a Mach message is received.\u003cbr /\u003e\u003cbr /\u003eBecause of this extra step, we now need to pay the price both of receiving a Mach message and communicating via a pipe between threads.  We've timed this approach and found it to be 10uSec slower on Desktops \u0026amp; 20uSecs faster on laptops than a pure pipe based implementation.\u003cbr /\u003e\u003cbr /\u003eIf you look at the measurements at the bottom of this document, you can see that most of the messages Chrome sends are very small.  So the performance benefits of Mach messages over pipes are negligible.\u003cbr /\u003e\u003cbr /\u003eThus our decision at this time is to use the same approach as Linux.  If we run into problems at a later date with a pipe-based implementation we can revert to the Mach-based one.\u003cbr /\u003e\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cbr /\u003e\u003ch3 style\u003d\"text-align:center\"\u003e\u003ca name\u003d\"TOC-Mach-based-IPC:\" /\u003e\u003cu\u003eMach based IPC:\u003c/u\u003e\u003c/h3\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n Summary of departures from current Windows architecture:\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cbr /\u003e\u003cu\u003ePC::Channel:\u003c/u\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e This class basically needs to be rewritten to use Mach ports, we\r\nrequire a bidirectional communication mechanism able to\r\ntransfer arbitrarily sized messages.  This means we need to create two\r\nMach ports (Server-\u0026gt;Client \u0026amp; Client-\u0026gt;Server).\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cu\u003eEstablishing\u003c/u\u003e\u003cu\u003e Communications:\u003c/u\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n (From chrome/common/ipc_channel.h)\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e \u003c/font\u003e\u003cspan style\u003d\"color:rgb(170,13,145)\"\u003eenum\u003c/span\u003e\u003cfont size\u003d\"1\"\u003e Mode { \u003c/font\u003e\r\n \u003c/p\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e     MODE_SERVER, \u003c/font\u003e\r\n \u003c/p\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e     MODE_CLIENT \u003c/font\u003e\r\n \u003c/p\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e   }; \u003c/font\u003e\r\n \u003c/p\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cspan style\u003d\"font-family:Monaco\"\u003e\u003cfont size\u003d\"1\"\u003eIPC::Channel::Channel(\u003c/font\u003e\u003cspan style\u003d\"color:rgb(170,13,145)\"\u003econst\u003c/span\u003e\u003cfont size\u003d\"1\"\u003e std::wstring\u0026amp; channel_id, Mode mode, Listener* listener);\u003c/font\u003e\u003c/span\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cspan style\u003d\"font-family:Monaco\"\u003e\u003cfont size\u003d\"1\"\u003e \u003c/font\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e \u003c/font\u003e\u003cspan style\u003d\"color:rgb(170,13,145)\"\u003ebool\u003c/span\u003e\u003cfont size\u003d\"1\"\u003e Connect(); \u003c/font\u003e\r\n \u003c/p\u003e\r\n \u003cfont size\u003d\"1\"\u003e \u003c/font\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003c/p\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Monaco\"\u003e\u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\u003cfont size\u003d\"1\"\u003e\r\n \u003c/font\u003e\r\n \u003c/p\u003e\r\n \u003cfont size\u003d\"1\"\u003e \u003c/font\u003e\u003c/span\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e When a Channel is created in Server mode it creates a Mach port\r\nand registers it with the Bootstrap server using the channel_id\r\nprefixed with the string 'chrome_'.  It then sets \u003cspan style\u003d\"font-family:Monaco\"\u003e\u003cfont size\u003d\"1\"\u003ewaiting_connect_\u003c/font\u003e\u003c/span\u003e to false.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cdiv style\u003d\"text-align:left\"\u003e\r\nWhen a Child process is started, it's passed the channel id and an authorization token via stdin (since that's not visible to other processes on the system).\r\n\u003c/div\u003e\r\n \u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e When a Channel is opened in Client mode, the Channel ID is\r\nlooked up on the Bootstrap server.  The client then creates a Mach port\r\nfor incoming messages, it sends a Hello message to the server\r\ncontaining port rights to its incoming port and the authorization token sent over the pipe.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n Upon receiving a Hello message, the Server verifies the token, if it's valid, it stores the send port rights and sets \u003cspan style\u003d\"font-family:Monaco\"\u003e\u003cfont size\u003d\"1\"\u003ewaiting_connect_\u003c/font\u003e\u003c/span\u003e to false.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cbr /\u003eServer-\u0026gt;Client.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cu\u003eSending Messages:\u003c/u\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n (From chrome/common/ipc_channel.h)\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"color:rgb(170,13,145)\"\u003ebool\u003c/span\u003e\u003cfont size\u003d\"1\"\u003e Send(Message* message); \u003c/font\u003e\r\n \u003c/p\u003e\r\n \u003cp style\u003d\"margin:0px;font-family:Monaco;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;font-size-adjust:none;font-stretch:normal\"\u003e\r\n \u003cfont size\u003d\"1\"\u003e\u003cbr /\u003e\r\n \u003c/font\u003e\r\n \u003c/p\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n Mach ports have a fixed queue size, we want to be able to send arbitrary numbers of messages without blocking.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e Messages to send over the wire are queued up on the Server side\r\nin an std::vector\u0026lt;Message*\u0026gt;, we specify a timeout value when\r\nsending a Mach message, if the send times out then we set a delayed\r\ntask to attempt to resend the message after a delta.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n When IPC::Channel::Send() is called, we attempt to send out all the messages in our outgoing queue until we block.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cu\u003eReceiving messages:\u003c/u\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e Messages can be an size up to 256MB, this presents a problems\r\nsince we don't want to allocate a 256MB buffer to receive messages\r\ninto.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n We can allocate an input buffer of a reasonable size, and specify the \u003cspan style\u003d\"font-family:Times\"\u003e\u003cfont size\u003d\"3\"\u003eMACH_RCV_LARGE \u003c/font\u003e\u003cspan style\u003d\"font-family:Verdana\"\u003e\u003cfont size\u003d\"2\"\u003eflag\r\nwhen receiving messages, if the message doesn't fit into our buffer\r\nthen we get a chance to dynamically allocate a new receive buffer and\r\nstick our data in there.\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e We will probably also want to look at large messages and send\r\nthose over as OOL transfer (OS X Internals 9.5.5) so that they're\r\ntransferred with copy-on-write semantics.\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e\r\n \u003cu\u003eSecurity:\u003cbr /\u003e\u003c/u\u003eThe initial security token provides security in the face of rogue client processes trying to connect back to a server, we can use the OS X Authorization Services API \u0026amp; AuthorizationMakeExternalForm() to generate the token.\u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003c/div\u003e We can make use of Mach's sender security token (OS X Internals\r\n9.2.2.3) to prevent processes not owned by the user from communicating\r\nwith the server.\u003cbr /\u003e\u003cbr /\u003e\r\n \r\n \r\n \u003cdiv style\u003d\"text-align:center\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Rationale-for-using-Mach-ports:\" /\u003e\u003cu\u003e\u003cfont size\u003d\"4\"\u003eRationale for using Mach ports:\u003c/font\u003e\u003c/u\u003e\u003c/h2\u003e\r\n \r\n \r\n \u003c/div\u003e\r\n \r\n \r\n \u003cfont size\u003d\"3\"\u003e\u003cu\u003eCurrent Windows implementation:\u003c/u\u003e\u003c/font\u003e\u003cbr /\u003e\u003cdiv\u003e\r\n \u003cbr /\u003e\r\nThe IPC::Channel object (chrome/common/ipc_channel.h) sends/receives\r\ndiscrete messages [length/byte array] over a bidirectional named pipe.\u003cbr /\u003e\r\n \u003cbr /\u003e\r\n Messages are limited to be less than 256MB, but can otherwise be of arbitrary size.\u003cbr /\u003e\r\n \u003cbr /\u003e\r\nThe pipe name is passed as a parameter to new rendering processes. \r\nThis is useful for debugging purposes since you can connect an\r\narbitrary rendering process to a browser instance.\u003cbr /\u003e\r\n \u003cbr /\u003e\r\n \u003cu\u003eSharing resources between processes:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cbr /\u003e\r\n Windows OS Handles can be shared between processes by calling \u003cspan style\u003d\"font-family:Courier New\"\u003eDuplicateHandle()\u003c/span\u003e,\r\nthis duplicates the handle into the target process and returns an ID\r\nvalid in that process.  This ID can then be sent as POD over the IPC\r\nChannel .  This is very convenient since it means that they can just be\r\nwrapped in an arbitrary messagen and send over the wire, but it's a\r\nvery Windows-specific capability.  There are currently 45 calls to \u003cspan style\u003d\"font-family:Courier New\"\u003eDuplicateHandle()\u003c/span\u003e in the code (Not all of these are necessarily used for IPC).\u003cbr /\u003e\r\n \u003cbr /\u003e\r\n \u003cu\u003e\u003cfont size\u003d\"3\"\u003eOS X Implementation:\u003c/font\u003e\u003c/u\u003e\u003cbr /\u003e\r\n \u003cbr /\u003e\r\n We basically have two options for implementation here worth discussing:\u003cbr /\u003e\r\n \u003cbr /\u003e\r\n \u003cu\u003eFIFO:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cu\u003eAdvantages:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cul\u003e\u003cli\u003e\r\n Very close to the current Windows implementation.\r\n \u003c/li\u003e\u003cli\u003e\r\n Might be shareable with Linux port.\r\n \u003c/li\u003e\u003cli\u003e\r\n Access control via full file system owner/permissions/ACL semantics\r\n \u003c/li\u003e\u003c/ul\u003e\r\n \u003cbr /\u003e\r\n \u003cu\u003eDisadvantages:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cul\u003e\u003cli\u003e\r\n Provides no mechanism to transmit mach semaphores and other system resources over the connection.\r\n \u003c/li\u003e\u003cli\u003e\r\n Messy, lives in the file system.\r\n \u003c/li\u003e\u003cli\u003e\r\n OS X may have quirks that prevent us from sharing the implementation with Linux.\r\n \u003c/li\u003e\u003c/ul\u003e\r\n \u003cbr /\u003e\r\n \u003cu\u003eMach ports:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cu\u003eAdvantages:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cul\u003e\u003cli\u003e\r\n Fast:\r\n \u003c/li\u003e\u003cul\u003e\u003cli\u003e\r\n pretty much any other IPC API we might use is already layered on top of this.\r\n \u003c/li\u003e\u003cli\u003e\r\n Does everything it can to remap memory rather than copy data.\r\n \u003c/li\u003e\u003cli\u003e\r\n Facilities to send over mem. buffers by remapping them via copy-on-write (OOL).\r\n \u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\r\n Secure - bunch of security primitives.\r\n \u003c/li\u003e\u003cli\u003e\r\n Allows us to send unnamed system resources such as semaphores and shared memory regions to another process.\r\n \u003c/li\u003e\u003c/ul\u003e\r\n \u003cbr /\u003e\r\n \u003cu\u003eDisadvantages:\u003c/u\u003e\u003cbr /\u003e\r\n \u003cul\u003e\u003cli\u003e\r\n OS X Specific.\r\n \u003c/li\u003e\u003cli\u003e\r\n Message based rather than stream based so if we get large messages we potentially need to copy them multiple times.\r\n \u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv style\u003d\"text-align:right\"\u003e\r\n\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"text-align:center\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Performance-Considerations\" /\u003e\u003cu\u003ePerformance Considerations\u003c/u\u003e\u003c/h2\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv\u003e What follows are the results of some benchmarks we ran contrasting Mach messaging and FIFO's.\u003cbr /\u003e\r\n\u003cbr /\u003e We tested Mach ports using both inline \u0026amp; out of line (OOL) data transfer.  Inline transfer means the payload is transferred as part of the message and copied into the receiving process.  OOL remaps the memory area using copy-on-write semantics.\u003cdiv\u003e\u003cbr /\u003e The executive summary is that Mach messages are faster than FIFOs on OS X, especially if we transfer messages larger than a certain threshold using OOL.\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cu\u003eTechnical Detail:\u003c/u\u003e\u003cdiv\u003e\u003cbr /\u003e The tables below contain the results from the following test programs:\u003cbr /\u003e\u003c/div\u003e\u003cul\u003e\u003cli\u003eMach - spawn two processes and send mach messages containing an inline buffer of the requisite size between them.\u003c/li\u003e\u003cli\u003eMach OOL - Same as MachPerf but sends the data OOL.\u003c/li\u003e\u003cli\u003eFIFO - spawn a new process and read/write data over a FIFO.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e Our testing methodology was to send over 2000 messages, times are in uSec and the ones shown represent the 98th percentile of the measured data.  Variance of all values is ~10uSec, possibly higher.\u003cbr /\u003e\u003cbr /\u003e\u003cu\u003eDiscussion:\u003c/u\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003eInline Mach messages take a performance hit for message sizes \u0026gt;5K, below that they are ~1.5X FIFOS on a 4 core Mac desktop and 280%-1000% faster than FIFOs a Laptop.\u003cbr /\u003e\u003cdiv\u003e  \u003cbr /\u003e The desktop/laptop difference is something we see consistently.\u003cbr /\u003e\u003cbr /\u003eOOL transfer has a constant overhead of ~30uSec which appears to be a clear win over any method that copies data between processes.\u003cu\u003e\u003cbr /\u003e\u003c/u\u003e\u003c/div\u003e\u003cbr /\u003e\u003cu\u003eThe data (times in uSec +/- 10uSec):\u003c/u\u003e\u003cbr /\u003e\u003cbr /\u003eLaptop:\u003cbr /\u003e\r\n\u003cbr /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003ePacket Size (bytes)  Mach    Mach OOL   FIFO           % min(Mach,Mach OOL) better than FIFO\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e100                  29      35         112            386                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e200                  10      37         121            1210                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e500                  11      36         124            1127                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e1024                 9       36         115            1277                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e2048                 28      37         131            467                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e3072                 11      39         129            1172                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e4096                 11      29         128            1163                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e5120                 13      31         127            976                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e6144                 51      30         134            446                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e7168                 46      30         133            443                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e8192                 51      32         215            671                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e9216                 57      30         218            726                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e1048576              1477    29         2873           9906                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e5242880              11079   39         10924          28010               \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e7340032              15144   38         14184          37326               \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e                                                   \u003c/span\u003e\u003cbr /\u003eDesktop:                      \u003cdiv dir\u003d\"ltr\"\u003e                     \u003cbr /\u003e                                                   \u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003ePacket Size (bytes)  Mach    Mach OOL   FIFO           % min(Mach,Mach OOL) better than FIFO\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e100                  10      26         29             290                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e200                  11      26         30             272                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e500                  12      29         30             250                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e1024                 11      34         30             272                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e2048                 15      36         31             206                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e3072                 16      39         32             200                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e4096                 14      29         36             257                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e5120                 19      25         37             194                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e6144                 66      27         34             125                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e7168                 53      26         38             146                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e8192                 70      26         59             226                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e9216                 81      25         66             264                 \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e1048576              1822    33         2623           7948                \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\r\n\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e5242880              11536   37         13125          35472               \u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e7340032              15693   41         17960          43804\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"text-decoration:underline\"\u003eDistribution of IPC Message Sizes In The Current Windows Implementation\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe following histogram was added to IPC::Channel::Send(), and measures an hour long browsing session including Gmail, YouTube, Hulu, CNN and other random sites. We see that:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e90% of messages are less than 65 bytes\u003c/li\u003e\u003cli\u003e99.9% of messages are less than 2400 bytes\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial;font-size:13px\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003eHistogram: IPC.MessageSize recorded 37573 samples, average \u003d 86.4, standard deviation \u003d 329.5\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e     0 ... \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    12 ---------------------O                                                    (4387 \u003d 11.7%) {0.0%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    16 ----O                                                                     (990 \u003d 2.6%) {11.7%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    21 -----------------------------------O                                      (9307 \u003d 24.8%) {14.3%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    28 O                                                                         (10 \u003d 0.0%) {39.1%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    37 O                                                                         (8 \u003d 0.0%) {39.1%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    49 ------------------------------------------------------------------------O (19123 \u003d 50.9%) {39.1%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    65 --O                                                                       (614 \u003d 1.6%) {90.0%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e    86 O                                                                         (38 \u003d 0.1%) {91.7%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   113 O                                                                         (113 \u003d 0.3%) {91.8%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   149 O                                                                         (34 \u003d 0.1%) {92.1%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   196 O                                                                         (110 \u003d 0.3%) {92.2%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   258 --O                                                                       (663 \u003d 1.8%) {92.4%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   340 ---O                                                                      (783 \u003d 2.1%) {94.2%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   448 --O                                                                       (653 \u003d 1.7%) {96.3%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   590 --O                                                                       (443 \u003d 1.2%) {98.0%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e   777 -O                                                                        (198 \u003d 0.5%) {99.2%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  1023 O                                                                         (72 \u003d 0.2%) {99.7%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  1347 O                                                                         (6 \u003d 0.0%) {99.9%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  1774 O                                                                         (5 \u003d 0.0%) {99.9%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  2336 O                                                                         (1 \u003d 0.0%) {100.0%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  3077 ... \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e 12196 O                                                                         (15 \u003d 0.0%) {100.0%}\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e 16063 ... \u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/os-x-interprocess-communication"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6176481638539759221"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6176481638539759221"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6176481638539759221"}],"author":[{"name":{"$t":"Jeremy Moskovich"},"email":{"$t":"jeremy@chromium.org"}}],"sites$pageName":{"$t":"os-x-interprocess-communication"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/585192261713360492"},"published":{"$t":"2015-04-17T22:25:07.241Z"},"updated":{"$t":"2015-04-17T22:35:32.302Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-17T22:35:31.222Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Touch Firmware Tests"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"display:block;margin-right:auto;margin-top:5px;margin-bottom:0px;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/for-testers/touch-firmware-tests/TouchFWTests.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\r\n\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Preparing-the-Testing-Host\"\u003e\u003cstrong\u003e1 \u003c/strong\u003ePreparing the Testing Host\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Initial-setup\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eInitial setup\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Updating-to-the-Latest-Version\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003eUpdating to the Latest Version\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Preparing-the-DUT\"\u003e\u003cstrong\u003e2 \u003c/strong\u003ePreparing the DUT\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Android-Devices\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eAndroid Devices\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-Devices\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eChrome Devices\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Running-the-Test\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eRunning the Test\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"94\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1429309744059/for-testers/touch-firmware-tests/TouchFWTests.png\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\r\n\u003cspan style\u003d\"color:red\"\u003e\r\n\r\n\r\n\u003c/span\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Preparing-the-Testing-Host\" /\u003ePreparing the Testing Host\u003c/h2\u003e\r\n\r\n\r\n\u003cp\u003eThese instructions describe how to set up the code and its dependencies on the\r\nhost, the workstation you will actually be running the tests \u003cem\u003efrom\u003c/em\u003e. Usually the host is a normal development machine. It is not the device under\r\ntest (DUT). \u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Initial-setup\" /\u003eInitial setup\u003c/h3\u003e\r\n\r\n\r\n\u003cp\u003eThe first time you configure the host to run touch firmware tests, the\r\nfollowing steps are required:\u003c/p\u003e\r\n\r\n\u003col\u003e\r\n \u003cli\u003e Clone the git repo that contains the test scripts. It is possible to clone the\r\nrepo without a full Chrome OS checkout, by running the following:\r\n\u003ccode\u003egit clone \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/platform/touch_firmware_test.git\"\u003ehttps://chromium.googlesource.com/chromiumos/platform/touch_firmware_test.git\u003c/a\u003e\u003c/code\u003e\r\n\r\nThis command creates a new \u003ccode\u003etouch_firmware_test\u003c/code\u003e directory in your working directory, containing a number of Python scripts.\r\n \u003c/li\u003e\r\n\u003cli\u003e Install the \u003ca href\u003d\"http://www.pyqtgraph.org/\" rel\u003d\"nofollow\"\u003ePyQtGraph\u003c/a\u003e plotting library, which is a dependency for the touch firmware tests. Use the\r\nprovided installers for Ubuntu and Windows and follow the instructions on \u003ca href\u003d\"http://www.pyqtgraph.org\" rel\u003d\"nofollow\"\u003ewww.pyqtgraph.org\u003c/a\u003e to install this library.\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Updating-to-the-Latest-Version\" /\u003eUpdating to the Latest Version\u003c/h3\u003e\r\n\r\n\r\n\u003cp\u003eIf you have previously checked out the test source code, simply pull the latest\r\npatches from the git server by navigating to the \u003ccode\u003etouch_firmware_test\u003c/code\u003e directory and running the \u003ccode\u003egit pull\u003c/code\u003e command.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Preparing-the-DUT\" /\u003ePreparing the DUT\u003c/h2\u003e\r\n\r\n\r\n\u003cp\u003eThe firmware test works for both Android and Chrome devices. However,\r\nconfiguration steps vary according to the type of DUT you are testing.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Android-Devices\" /\u003eAndroid Devices\u003c/h3\u003e\r\n\r\n\r\n\u003col\u003e\r\n \u003cli\u003e Verify \u003ccode\u003eadb\u003c/code\u003e is installed on the testing host. You can follow the steps \u003ca href\u003d\"https://docs.google.com/document/d/1nRsKr6wZi5sWmdgzCy9Cx7yPykcuxu9gFccXroRLxBI\"\u003edescribed on this page\u003c/a\u003e or use a different procedure that works for your environment.\r\n \u003c/li\u003e\r\n\u003cli\u003e Connect your Android device to the testing host.\u003cstrong\u003e \u003c/strong\u003eOn the host, you must be able to connect to the DUT via \u003ccode\u003eadb\u003c/code\u003e. In the simple case the DUT is physically connected to the host via USB. Other\r\nconfigurations, such as adb-over-wifi, are also possible, as long as \u003ccode\u003eadb\u003c/code\u003e can communicate with the DUT.\r\n \u003c/li\u003e\r\n\u003cli\u003e Enable USB Debugging on the DUT. Using \u003ca href\u003d\"http://www.greenbot.com/article/2457986/how-to-enable-developer-options-on-your-android-phone-or-tablet.html\" rel\u003d\"nofollow\"\u003ethese instructions\u003c/a\u003e or similar steps, enable Developer options on the Android device. In the\r\nDeveloper options panel, select USB debugging. The exact procedure depends on\r\nthe device. If you cannot locate these features on your device, search the\r\nInternet for “USB debugging \u0026lt;\u003cem\u003eyour-device-type\u003c/em\u003e\u0026gt;”.\r\n \u003c/li\u003e\r\n\u003cli\u003e Verify the configuration of your DUT and testing host by running \u003ccode\u003eadb shell\u003c/code\u003e in a terminal window on the host. It should open a terminal connection to the\r\nDUT with a command prompt.\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Chrome-Devices\" /\u003eChrome Devices\u003c/h3\u003e\r\n\r\n\r\n\u003col\u003e\r\n \u003cli\u003e Install a Chrome OS test image on the DUT. A test image is required (versus a normal Chrome OS image) to allow the\r\nfirmware test to use ssh, evtest, and other testing utilities not included in\r\nrelease images. To get a test image, from within your chroot run the following: \u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003ecd ~/trunk/scripts\r\n./build_packages --board\u003d$BOARD\r\n./buildimage --board\u003d$BOARD\r\n--noenable_rootfs_verification test \u003cbr /\u003e\r\n\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ewhere \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003eBOARD\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e is the board name used in the Chrome device (also the name of the private\r\noverlay). Install the resulting image on the DUT.\u003c/span\u003e\u003c/blockquote\u003e\r\n\u003col start\u003d\"2\"\u003e\r\n\u003cli\u003e Connect the DUT to a network the testing host can access. A USB-Ethernet adapter connected to a LAN is recommended, to minimize lag\r\nand dropped connections. It is also feasible to use a wireless connection.\r\n \u003c/li\u003e\r\n\u003cli\u003e Verify the configuration of your DUT and testing host by running the command \u003ccode\u003essh root@$DUT_IP\u003c/code\u003e to connect to the DUT via SSH. If prompted for a password, use \u003ccode\u003etest0000\u003c/code\u003e. A connection to the DUT should be established.\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Running-the-Test\" /\u003eRunning the Test\u003c/h2\u003e\r\n\r\n\r\n\u003col\u003e\r\n \u003cli\u003e On the testing host, navigate to the \u003ccode\u003etouch_firmware_test\u003c/code\u003e directory and run either:\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003epython main.py -t chromeos -a $IP_ADDRESS \u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003efor Chrome devices, or: \u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003epython main.py -t android [-a $DEVICE_STRING] \u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003efor Android devices. To display additional command line parameters that\r\nconfigure the way the test runs, run \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003epython main.py --help\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e .\u003c/span\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\r\n\u003col start\u003d\"2\"\u003e\u003cli\u003e Follow the screen prompts and perform the gestures indicated on the touchpad or\r\ntouchscreen of the DUT.\r\n \u003c/li\u003e\r\n\u003cli\u003e When all the tests have run, a file named \u003ccode\u003ereport.html\u003c/code\u003e is generated. Open this file in a browser to view the results.\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3087306851372487833"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/for-testers/touch-firmware-tests"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/585192261713360492"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/585192261713360492"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/585192261713360492"}],"author":[{}],"sites$pageName":{"$t":"touch-firmware-tests"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1843594305301410560"},"published":{"$t":"2015-04-17T22:29:04.027Z"},"updated":{"$t":"2015-04-17T22:29:04.059Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-17T22:29:04.027Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"TouchFWTests.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1843594305301410560"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/585192261713360492"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/for-testers/touch-firmware-tests/TouchFWTests.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1843594305301410560"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1843594305301410560"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1843594305301410560"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1843594305301410560"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7028024001906908915"},"published":{"$t":"2015-04-03T20:40:57.072Z"},"updated":{"$t":"2015-04-17T06:56:59.458Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-03T20:49:27.073Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"OpenVPN Manual Setup"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eTODO: Merge this content into the Chrome OS format.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis document, \u003ca href\u003d\"https://docs.google.com/document/d/18TU22gueH5OKYHZVJ5nXuqHnk2GN6nDvfu2Hbrb4YLE/pub\"\u003eOpenVPN on ChromeOS\u003c/a\u003e  (published Google Doc format) contains step by step instructions on getting customized OpenVPN client settings on ChromeOS.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe first part discusses setting up an OpenVPN server (which you can skip if you already have one) and the second shows how to import the necessary certificates into your ChromeOS machine, and finally the last part sets up the network config settings as an ONC file which is then imported into ChromeOS.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eNote:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThis does not require a machine to be in developer mode, and can run on a standard ChromeOS image.\u003c/span\u003e\u003c/li\u003e\u003cli\u003eGoogle enterprise customers may have access to easier methods of doing this via the ChromeOS device administration features of your account, where an ONC policy can be installed at sign on. These instructions here should work as well, but were intended for use on consumer (e.g. @gmail.com) google profiles.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/openvpn-manual-setup"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7028024001906908915"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7028024001906908915"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7028024001906908915"}],"author":[{}],"sites$pageName":{"$t":"openvpn-manual-setup"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},"published":{"$t":"2015-04-10T20:51:38.236Z"},"updated":{"$t":"2015-04-10T21:03:43.849Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T21:03:42.434Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"LG Chromebase 22CV241-W"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"https://www.google.com/chromebook/\"\u003eLenovo Chromebook N20 \u0026amp; N20P\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\u003cp\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699184077/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-1-F-101_White_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699187218/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-2-F-101_Black_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699192760/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-3-B-113_White_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699195328/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-4-B-113_Black_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699198620/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-5-B-102F_White_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699202715/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-6-B-102F_Black_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699206071/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-7-S-103_White_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699181264/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-8-S-103_Black_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699212666/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-9-S-102_White_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699215629/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-10-S-102_Black_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699218817/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-11-S-101_White_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428699221600/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-12-S-101_Black_Monitor_from-Sandbox.jpg\" width\u003d\"200\" /\u003e\r\n\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eWeight: 2.87 lbs\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eCPU: Haswell Intel Celeron Dual-Core \u003ca href\u003d\"http://ark.intel.com/products/75608/Intel-Celeron-Processor-2955U-2M-Cache-1_40-GHz\" rel\u003d\"nofollow\"\u003e2955U\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GiB DDR3 (1 upgradable slot)\u003c/li\u003e\r\n\u003cli\u003eDisplay: 21.5\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\" \u003c/span\u003e1920x1080 16:9\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eDisk: 16GB SSD\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eI/O:\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI\u003c/li\u003e\r\n\u003cli\u003e3 x USB 2.0\u003c/li\u003e\r\n\u003cli\u003e1 x USB 3.0\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\r\n\u003cli\u003eCamera \u0026amp; mic\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n/ac\u003c/li\u003e\r\n\u003cli\u003eBluetooth 4.0\u003c/li\u003e\r\n\u003cli\u003e100/1000 Ethernet\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eLinux 3.8\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eDetails for working with developer mode can be found \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook\"\u003eon this page\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-monroe-4921.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-monroe-4921.B\u003c/code\u003e branch.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process. Really, just don't.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your Chromebook is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center. There's nothing inside that you can fix yourself. Be advised that disassembly might \u003cb\u003evoid warranties\u003c/b\u003e or other obligations, so please consult any and all paperwork you received first.\u003c/p\u003e\r\n\r\n\u003cp\u003eFine. If you \u003cb\u003emust\u003c/b\u003e risk breaking it for good, at least do it the right way.\u003c/p\u003e\r\n\u003cul\u003e\r\n\u003cli\u003eFirst, acquire the necessary tools:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eA small Phillips head screw driver\u003c/li\u003e\r\n\u003cli\u003eA large Philips head screw driver\u003c/li\u003e\r\n\u003cli\u003eA \u003ca href\u003d\"http://en.wikipedia.org/wiki/Spudger\" rel\u003d\"nofollow\"\u003espudger\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003ePlace the computer screen down on a flat surface\u003c/li\u003e\r\n\u003cli\u003ePop the plastic cap with the cable holder off the back by pulling from the top\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eRemove the three exposed screws in the middle\u003c/li\u003e\r\n\u003cli\u003ePull the stand off\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove the one visible screw near the USB ports on the back\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003ePry the central plastic piece of carefully\u003c/li\u003e\r\n\u003cli\u003eTry flexing it and pulling from the bottom part\u003c/li\u003e\r\n\u003cli\u003eThe spudger might help\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove the three visible screws and detach the cables\u003c/li\u003e\r\n\u003cli\u003eStarting at the bottom, of the screen, there should be a plastic hole\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eStart prying apart the case from there using the spudger\u003c/li\u003e\r\n\u003cli\u003eWork all the way around the top\u003c/li\u003e\r\n\u003cli\u003ePull the back off\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove the visible screws from the metal bracket to expose the motherboard\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4555311320229718241"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"lg-chromebase-22cv241-w"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8315488723851347468"},"published":{"$t":"2015-04-10T20:53:41.566Z"},"updated":{"$t":"2015-04-10T20:53:41.600Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:41.566Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-12-S-101_Black_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8315488723851347468"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-12-S-101_Black_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8315488723851347468"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8315488723851347468"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8315488723851347468"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8315488723851347468"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1410122624956963699"},"published":{"$t":"2015-04-10T20:53:38.767Z"},"updated":{"$t":"2015-04-10T20:53:38.817Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:38.767Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-11-S-101_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1410122624956963699"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-11-S-101_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1410122624956963699"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1410122624956963699"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1410122624956963699"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1410122624956963699"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6063223360939786252"},"published":{"$t":"2015-04-10T20:53:35.592Z"},"updated":{"$t":"2015-04-10T20:53:35.629Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:35.592Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-10-S-102_Black_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6063223360939786252"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-10-S-102_Black_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6063223360939786252"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6063223360939786252"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6063223360939786252"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6063223360939786252"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4631554133343771377"},"published":{"$t":"2015-04-10T20:53:32.609Z"},"updated":{"$t":"2015-04-10T20:53:32.666Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:32.609Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-9-S-102_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4631554133343771377"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-9-S-102_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4631554133343771377"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4631554133343771377"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4631554133343771377"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4631554133343771377"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3656176219013546377"},"published":{"$t":"2015-04-10T20:53:26.029Z"},"updated":{"$t":"2015-04-10T20:53:26.071Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:26.029Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-7-S-103_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3656176219013546377"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-7-S-103_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3656176219013546377"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3656176219013546377"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3656176219013546377"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3656176219013546377"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1705665941216055807"},"published":{"$t":"2015-04-10T20:53:22.665Z"},"updated":{"$t":"2015-04-10T20:53:22.715Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:22.665Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-6-B-102F_Black_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1705665941216055807"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-6-B-102F_Black_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1705665941216055807"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1705665941216055807"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1705665941216055807"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1705665941216055807"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6061491540392594366"},"published":{"$t":"2015-04-10T20:53:18.575Z"},"updated":{"$t":"2015-04-10T20:53:18.620Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:18.575Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-5-B-102F_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6061491540392594366"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-5-B-102F_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6061491540392594366"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6061491540392594366"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6061491540392594366"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6061491540392594366"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3705670124354486680"},"published":{"$t":"2015-04-10T20:53:15.287Z"},"updated":{"$t":"2015-04-10T20:53:15.328Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:15.287Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-4-B-113_Black_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3705670124354486680"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-4-B-113_Black_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3705670124354486680"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3705670124354486680"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3705670124354486680"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3705670124354486680"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/166982444667157964"},"published":{"$t":"2015-04-10T20:53:12.716Z"},"updated":{"$t":"2015-04-10T20:53:12.760Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:12.716Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-3-B-113_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/166982444667157964"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-3-B-113_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/166982444667157964"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/166982444667157964"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/166982444667157964"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/166982444667157964"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5999175307410322509"},"published":{"$t":"2015-04-10T20:53:07.179Z"},"updated":{"$t":"2015-04-10T20:53:07.218Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:07.179Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-2-F-101_Black_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5999175307410322509"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-2-F-101_Black_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5999175307410322509"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5999175307410322509"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5999175307410322509"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5999175307410322509"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6138468535543503574"},"published":{"$t":"2015-04-10T20:53:04.041Z"},"updated":{"$t":"2015-04-10T20:53:04.077Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:04.041Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-1-F-101_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6138468535543503574"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-1-F-101_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6138468535543503574"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6138468535543503574"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6138468535543503574"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6138468535543503574"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7387411081198169881"},"published":{"$t":"2015-04-10T20:53:01.219Z"},"updated":{"$t":"2015-04-10T20:53:01.264Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:53:01.219Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-8-S-103_Black_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7387411081198169881"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-8-S-103_Black_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7387411081198169881"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7387411081198169881"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7387411081198169881"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7387411081198169881"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7862875503462934218"},"published":{"$t":"2015-04-10T20:52:49.950Z"},"updated":{"$t":"2015-04-10T20:52:49.985Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-10T20:52:49.950Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LG-1-card-F-101_White_Monitor_from-Sandbox.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7862875503462934218"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4555311320229718241"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lg-chromebase-22cv241-w/gallery-LG-1-card-F-101_White_Monitor_from-Sandbox.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7862875503462934218"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7862875503462934218"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7862875503462934218"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7862875503462934218"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},"published":{"$t":"2015-04-09T05:40:49.883Z"},"updated":{"$t":"2015-04-10T03:22:27.676Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:12:40.509Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Acer C910 Chromebook 15"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"https://store.google.com/product/acer_chromebook_15\"\u003eAcer Chromebook 15 (C910)\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\u003cp\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559785132/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0000_Acer-Chromebook-15-01-front.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559791188/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0001_Acer-Chromebook-15-02-left.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559802656/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0002_Acer-Chromebook-15-03-right.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559810235/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0003_Acer-Chromebook-15-04-side-left.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559817312/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0004_Acer-Chromebook-15-05-side-right.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559823432/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0005_Acer-Chromebook-15-06-group-black.jpg\" width\u003d\"200\" /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1428559831863/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0006_Acer-Chromebook-15-07-group-white.jpg\" width\u003d\"200\" /\u003e\r\n\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003eDimensions: 383 x 256 x 24.2 mm\u003c/li\u003e\r\n\u003cli\u003eWeight: 2.2 kg (4.85 lbs)\u003c/li\u003e\r\n\u003cli\u003eCPU: Broadwell Intel Celeron Dual-Core \u003ca href\u003d\"http://ark.intel.com/products/74744/Intel-Core-i3-3250-Processor-3M-Cache-3_50-GHz\" rel\u003d\"nofollow\"\u003e3250U\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GiB or 4GiB DDR3 (Not upgradeable)\u003c/li\u003e\r\n\u003cli\u003eDisplay: \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e15.6\" \u003c/span\u003e1920x1080\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eDisk: 16GB or 32GB SSD\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eI/O:\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI port\u003c/li\u003e\r\n\u003cli\u003e1 x USB 2.0\u003c/li\u003e\r\n\u003cli\u003e1 x USB 3.0\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\r\n\u003cli\u003eCamera \u0026amp; mic\u003c/li\u003e\r\n\u003cli\u003eKeyboard \u0026amp; touchpad\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n/ac\u003c/li\u003e\r\n\u003cli\u003eBluetooth 4.0\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eUSB ports can handle some Ethernet dongles\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eLinux 3.14\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eDetails for working with developer mode can be found \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook\"\u003eon this page\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-yuna-6301.59.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-yuna-6301.59.B\u003c/code\u003e branch.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2394684821428822738"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"acer-c910-chromebook"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7055082763442804598"},"published":{"$t":"2015-04-09T07:01:50.751Z"},"updated":{"$t":"2015-04-09T07:01:50.783Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:50.751Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-7-side-right.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7055082763442804598"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-7-side-right.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7055082763442804598"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7055082763442804598"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7055082763442804598"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7055082763442804598"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4650797331367735686"},"published":{"$t":"2015-04-09T07:01:35.971Z"},"updated":{"$t":"2015-04-09T07:01:36.001Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:35.971Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-6-side-left.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4650797331367735686"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-6-side-left.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4650797331367735686"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4650797331367735686"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4650797331367735686"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4650797331367735686"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7092429513898307379"},"published":{"$t":"2015-04-09T07:01:33.475Z"},"updated":{"$t":"2015-04-09T07:01:33.508Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:33.475Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-5-hinge.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7092429513898307379"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-5-hinge.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7092429513898307379"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7092429513898307379"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7092429513898307379"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7092429513898307379"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8068583195957823937"},"published":{"$t":"2015-04-09T07:01:28.941Z"},"updated":{"$t":"2015-04-09T07:01:28.979Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:28.941Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-4-right.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8068583195957823937"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-4-right.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8068583195957823937"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8068583195957823937"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8068583195957823937"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8068583195957823937"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3986080259715903052"},"published":{"$t":"2015-04-09T07:01:23.896Z"},"updated":{"$t":"2015-04-09T07:01:23.931Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:23.896Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-3-left.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3986080259715903052"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-3-left.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3986080259715903052"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3986080259715903052"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3986080259715903052"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3986080259715903052"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7247353439533035306"},"published":{"$t":"2015-04-09T07:01:19.478Z"},"updated":{"$t":"2015-04-09T07:01:19.516Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:19.478Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-2-front.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7247353439533035306"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-2-front.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7247353439533035306"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7247353439533035306"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7247353439533035306"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7247353439533035306"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4588710922829244246"},"published":{"$t":"2015-04-09T07:01:14.837Z"},"updated":{"$t":"2015-04-09T07:01:14.869Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:14.837Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-1-hinge.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4588710922829244246"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-1-hinge.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4588710922829244246"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4588710922829244246"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4588710922829244246"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4588710922829244246"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8271531187777714096"},"published":{"$t":"2015-04-09T07:01:09.856Z"},"updated":{"$t":"2015-04-09T07:01:09.898Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T07:01:09.856Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-LenovoChromebookN20p-1-card-hinge.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8271531187777714096"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/839736656483527454"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-chromebook-n20/gallery-LenovoChromebookN20p-1-card-hinge.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8271531187777714096"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8271531187777714096"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8271531187777714096"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8271531187777714096"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2178715908313390041"},"published":{"$t":"2015-04-09T06:45:41.473Z"},"updated":{"$t":"2015-04-09T06:45:41.498Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:45:41.473Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-Acer-Chromebook13-5-side-right.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2178715908313390041"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5068133725317161446"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-cb5-311-chromebook-13/gallery-Acer-Chromebook13-5-side-right.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2178715908313390041"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2178715908313390041"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2178715908313390041"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2178715908313390041"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6843868576742613866"},"published":{"$t":"2015-04-09T06:45:38.337Z"},"updated":{"$t":"2015-04-09T06:45:38.369Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:45:38.337Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-Acer-Chromebook13-4-side-left.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6843868576742613866"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5068133725317161446"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-cb5-311-chromebook-13/gallery-Acer-Chromebook13-4-side-left.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6843868576742613866"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6843868576742613866"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6843868576742613866"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6843868576742613866"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6342467823307529454"},"published":{"$t":"2015-04-09T06:45:34.097Z"},"updated":{"$t":"2015-04-09T06:45:34.133Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:45:34.097Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-Acer-Chromebook13-3-right.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6342467823307529454"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5068133725317161446"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-cb5-311-chromebook-13/gallery-Acer-Chromebook13-3-right.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6342467823307529454"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6342467823307529454"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6342467823307529454"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6342467823307529454"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2067810394887034065"},"published":{"$t":"2015-04-09T06:45:29.813Z"},"updated":{"$t":"2015-04-09T06:45:29.845Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:45:29.813Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-Acer-Chromebook13-2-left.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2067810394887034065"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5068133725317161446"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-cb5-311-chromebook-13/gallery-Acer-Chromebook13-2-left.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2067810394887034065"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2067810394887034065"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2067810394887034065"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2067810394887034065"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4975371384412476758"},"published":{"$t":"2015-04-09T06:45:26.703Z"},"updated":{"$t":"2015-04-09T06:45:26.732Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:45:26.703Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-Acer-Chromebook13-1-front.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4975371384412476758"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5068133725317161446"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-cb5-311-chromebook-13/gallery-Acer-Chromebook13-1-front.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4975371384412476758"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4975371384412476758"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4975371384412476758"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4975371384412476758"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6783241339473035967"},"published":{"$t":"2015-04-09T06:45:24.567Z"},"updated":{"$t":"2015-04-09T06:45:24.597Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:45:24.567Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gallery-Acer-Chromebook13-1-card-front.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6783241339473035967"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5068133725317161446"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-cb5-311-chromebook-13/gallery-Acer-Chromebook13-1-card-front.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6783241339473035967"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6783241339473035967"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6783241339473035967"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6783241339473035967"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3799664603889830748"},"published":{"$t":"2015-04-09T06:38:41.394Z"},"updated":{"$t":"2015-04-09T06:38:41.428Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:41.394Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-8.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3799664603889830748"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-8.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3799664603889830748"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3799664603889830748"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3799664603889830748"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3799664603889830748"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8166596568672064513"},"published":{"$t":"2015-04-09T06:38:37.455Z"},"updated":{"$t":"2015-04-09T06:38:37.483Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:37.455Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-7.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8166596568672064513"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-7.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8166596568672064513"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8166596568672064513"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8166596568672064513"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8166596568672064513"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1565439514359513403"},"published":{"$t":"2015-04-09T06:38:29.955Z"},"updated":{"$t":"2015-04-09T06:38:29.984Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:29.955Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-6.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1565439514359513403"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-6.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1565439514359513403"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1565439514359513403"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1565439514359513403"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1565439514359513403"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3524414919445309109"},"published":{"$t":"2015-04-09T06:38:26.222Z"},"updated":{"$t":"2015-04-09T06:38:26.256Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:26.222Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-5.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3524414919445309109"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-5.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3524414919445309109"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3524414919445309109"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3524414919445309109"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3524414919445309109"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6275025096568658804"},"published":{"$t":"2015-04-09T06:38:23.443Z"},"updated":{"$t":"2015-04-09T06:38:23.469Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:23.443Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-4.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6275025096568658804"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-4.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6275025096568658804"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6275025096568658804"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6275025096568658804"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6275025096568658804"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5560487205842978932"},"published":{"$t":"2015-04-09T06:38:20.424Z"},"updated":{"$t":"2015-04-09T06:38:20.452Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:20.424Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-3.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5560487205842978932"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-3.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5560487205842978932"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5560487205842978932"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5560487205842978932"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5560487205842978932"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7997633465447017250"},"published":{"$t":"2015-04-09T06:38:15.440Z"},"updated":{"$t":"2015-04-09T06:38:15.469Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:15.440Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-2.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7997633465447017250"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-2.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7997633465447017250"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7997633465447017250"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7997633465447017250"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7997633465447017250"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5681001149129006200"},"published":{"$t":"2015-04-09T06:38:09.752Z"},"updated":{"$t":"2015-04-09T06:38:09.780Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:09.752Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"large-1.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5681001149129006200"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/large-1.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5681001149129006200"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5681001149129006200"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5681001149129006200"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5681001149129006200"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6465845458174107016"},"published":{"$t":"2015-04-09T06:38:04.768Z"},"updated":{"$t":"2015-04-09T06:38:04.800Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:38:04.768Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"hero.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6465845458174107016"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8028642474632465696"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-chromebook-14/hero.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6465845458174107016"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6465845458174107016"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6465845458174107016"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6465845458174107016"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7091851729662647298"},"published":{"$t":"2015-04-09T06:10:31.826Z"},"updated":{"$t":"2015-04-09T06:10:31.863Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:10:31.826Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0006_Acer-Chromebook-15-07-group-white.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7091851729662647298"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0006_Acer-Chromebook-15-07-group-white.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7091851729662647298"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7091851729662647298"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7091851729662647298"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7091851729662647298"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1351693469883178630"},"published":{"$t":"2015-04-09T06:10:23.404Z"},"updated":{"$t":"2015-04-09T06:10:23.432Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:10:23.404Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0005_Acer-Chromebook-15-06-group-black.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1351693469883178630"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0005_Acer-Chromebook-15-06-group-black.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1351693469883178630"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1351693469883178630"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1351693469883178630"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1351693469883178630"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2258492931775361292"},"published":{"$t":"2015-04-09T06:10:17.272Z"},"updated":{"$t":"2015-04-09T06:10:17.312Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:10:17.272Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0004_Acer-Chromebook-15-05-side-right.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2258492931775361292"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0004_Acer-Chromebook-15-05-side-right.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2258492931775361292"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2258492931775361292"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2258492931775361292"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2258492931775361292"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8338720592104256819"},"published":{"$t":"2015-04-09T06:10:10.208Z"},"updated":{"$t":"2015-04-09T06:10:10.235Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:10:10.208Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0003_Acer-Chromebook-15-04-side-left.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8338720592104256819"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0003_Acer-Chromebook-15-04-side-left.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8338720592104256819"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8338720592104256819"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8338720592104256819"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8338720592104256819"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7947778210853002852"},"published":{"$t":"2015-04-09T06:10:02.620Z"},"updated":{"$t":"2015-04-09T06:10:02.656Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:10:02.620Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0002_Acer-Chromebook-15-03-right.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7947778210853002852"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0002_Acer-Chromebook-15-03-right.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7947778210853002852"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7947778210853002852"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7947778210853002852"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7947778210853002852"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4296420792186437267"},"published":{"$t":"2015-04-09T06:09:51.154Z"},"updated":{"$t":"2015-04-09T06:09:51.188Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:09:51.154Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0001_Acer-Chromebook-15-02-left.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4296420792186437267"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0001_Acer-Chromebook-15-02-left.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4296420792186437267"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4296420792186437267"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4296420792186437267"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4296420792186437267"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4333114633521792303"},"published":{"$t":"2015-04-09T06:09:45.106Z"},"updated":{"$t":"2015-04-09T06:09:45.132Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-09T06:09:45.106Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_0001s_0000_Acer-Chromebook-15-01-front.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4333114633521792303"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2394684821428822738"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c910-chromebook/chromebook_0001s_0000_Acer-Chromebook-15-01-front.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4333114633521792303"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4333114633521792303"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4333114633521792303"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4333114633521792303"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1701955623604910541"},"published":{"$t":"2015-04-05T19:32:39.378Z"},"updated":{"$t":"2015-04-05T19:32:39.406Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-05T19:32:39.378Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromestatus42.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1701955623604910541"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8916636704403410309"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/when-will-a-fix-ship-in-chrome-stable-or-canary/chromestatus42.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1701955623604910541"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1701955623604910541"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1701955623604910541"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1701955623604910541"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/825369728599444098"},"published":{"$t":"2015-04-05T00:49:26.733Z"},"updated":{"$t":"2015-04-05T00:49:26.776Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-05T00:49:26.733Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-04-04 at 3.19.28 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/825369728599444098"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8916636704403410309"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/when-will-a-fix-ship-in-chrome-stable-or-canary/Screen%20Shot%202015-04-04%20at%203.19.28%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/825369728599444098"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/825369728599444098"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/825369728599444098"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/825369728599444098"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7855035955442577986"},"published":{"$t":"2015-04-05T00:39:52.113Z"},"updated":{"$t":"2015-04-05T00:39:52.238Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-05T00:39:52.113Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-04-04 at 5.38.39 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7855035955442577986"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8916636704403410309"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/when-will-a-fix-ship-in-chrome-stable-or-canary/Screen%20Shot%202015-04-04%20at%205.38.39%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7855035955442577986"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7855035955442577986"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7855035955442577986"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7855035955442577986"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8342352468603789546"},"published":{"$t":"2015-04-05T00:36:48.691Z"},"updated":{"$t":"2015-04-05T00:36:48.737Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-05T00:36:48.691Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-04-04 at 5.36.49 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8342352468603789546"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8916636704403410309"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/when-will-a-fix-ship-in-chrome-stable-or-canary/Screen%20Shot%202015-04-04%20at%205.36.49%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8342352468603789546"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8342352468603789546"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8342352468603789546"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8342352468603789546"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4421201614353372889"},"published":{"$t":"2015-04-04T23:18:40.994Z"},"updated":{"$t":"2015-04-04T23:18:41.025Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-04T23:18:40.994Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2015-04-04 at 4.18.39 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4421201614353372889"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8916636704403410309"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/when-will-a-fix-ship-in-chrome-stable-or-canary/Screen%20Shot%202015-04-04%20at%204.18.39%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4421201614353372889"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4421201614353372889"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4421201614353372889"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4421201614353372889"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2695177203938221028"},"published":{"$t":"2015-04-04T22:57:45.791Z"},"updated":{"$t":"2015-04-04T23:13:02.572Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-04T23:13:02.549Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Untitled-5.fw.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2695177203938221028"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8916636704403410309"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/blink/when-will-a-fix-ship-in-chrome-stable-or-canary/Untitled-5.fw.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2695177203938221028"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2695177203938221028"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2695177203938221028"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2695177203938221028"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5321757110955595249"},"published":{"$t":"2014-08-06T00:49:06.794Z"},"updated":{"$t":"2015-04-03T04:13:20.329Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-03T04:13:17.922Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Getting Started"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-For-web-developer-documentation-see:\" /\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003eFor web developer documentation, see:\u003c/span\u003e\u003c/h3\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://github.com/jakearchibald/simple-serviceworker-tutorial\" rel\u003d\"nofollow\"\u003eJake Archibald's \"simple-serviceworker-tutorial\"\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://www.html5rocks.com/en/tutorials/service-worker/introduction/\" target\u003d\"_blank\"\u003e\"Introduction to Service Worker\"\u003c/a\u003e at html5rocks.com\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://jakearchibald.com/2014/offline-cookbook/\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003e\"The Offline Cookbook\"\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://jakearchibald.github.io/isserviceworkerready/\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003e\"Is Service Worker Ready Yet?\"\u003c/a\u003e \u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you are a Chromium developer, read on!\u003c/div\u003e\u003cp\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eHere's how to get a demo Service Worker up and running:\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cb style\u003d\"font-size:10pt;background-color:transparent\"\u003eSteps:\u003c/b\u003e\u003c/p\u003e\r\n\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eOpen the demo at \u003c/span\u003e\u003ca href\u003d\"https://googlechrome.github.io/samples/service-worker/basic/index.html\" style\u003d\"font-size:10pt;background-color:transparent\" rel\u003d\"nofollow\"\u003ehttps://googlechrome.github.io/samples/service-worker/basic/index.html\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e  (\u003c/span\u003e\u003ca href\u003d\"https://github.com/GoogleChrome/samples\" style\u003d\"font-size:10pt;background-color:transparent\" rel\u003d\"nofollow\"\u003esource\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e) \u003c/span\u003e\u003c/li\u003e\u003cli\u003eOpen the Inspector. Things are logged there later on.\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eTry visiting Cleveland and get a 404. Go back.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eClick the 'Register' button, watch the Inspector console, then try visiting Cleveland again... \u003cb\u003e\u003ci\u003eoooh\u003c/i\u003e\u003c/b\u003e.\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;text-align:right;background-color:transparent\"\u003eGo to \u003cfont color\u003d\"#0b5394\"\u003echrome://inspect#service-workers\u003c/font\u003e and click on Inspect to open the Inspector and debug your Service Worker.\u003c/span\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\u003ch3 style\u003d\"text-align:left\"\u003e\u003ca name\u003d\"TOC-Running-it-locally\" /\u003eRunning it locally\u003c/h3\u003e\u003cdiv style\u003d\"text-align:right\"\u003e\u003cul style\u003d\"text-align:left\"\u003e\u003cli\u003eClone the \u003ca href\u003d\"https://github.com/GoogleChrome/samples\" rel\u003d\"nofollow\"\u003egit repo\u003c/a\u003e \u003c/li\u003e\u003cli\u003eNavigate to the samples/service-worker/basic folder\u003c/li\u003e\u003cli\u003eStart a local webserver (see below)\u003c/li\u003e\u003cli\u003eOpen http://localhost:8080/index.html (or whatever path and port you set up.) \u003c/li\u003e\u003cli\u003eFeel free to edit the JS and try some new things!\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch3 style\u003d\"text-align:left\"\u003e\u003ca name\u003d\"TOC-How-to-run-a-local-server\" /\u003eHow to run a local server\u003c/h3\u003e\r\n\u003cdiv style\u003d\"text-align:left\"\u003e\r\n\u003cdiv\u003eOn a system with python:\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;background-color:transparent\"\u003e$ python -m SimpleHTTPServer 8080\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eOn Android use Chrome Developer Tools' \u003ca href\u003d\"https://developer.chrome.com/devtools/docs/remote-debugging#enable-reverse-port-forwarding\"\u003eport forwarding\u003c/a\u003e.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Development-flow\" /\u003eDevelopment flow\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eIn order to guarantee that the latest version of your Service Worker script is being used, follow these instructions:\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eConfigure your local server to serve your Service Worker script as non-cacheable (cache-control: no-cache)\u003c/span\u003e\u003c/li\u003e\u003cli\u003eAfter you made changes to your service worker script:\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cb\u003eclose all but one\u003c/b\u003e of the tabs pointing to your web application\u003c/li\u003e\u003cli\u003ehit \u003cb\u003eshift-reload\u003c/b\u003e to bypass the service worker as to ensure that the remaining tab isn't under the control of a service worker\u003c/li\u003e\u003cli\u003ehit \u003cb\u003ereload\u003c/b\u003e to let the newer version of the Service Worker control the page.\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Documentation\" /\u003eDocumentation\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eFor an overview of the possibilities: Jake's \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"https://www.youtube.com/watch?v\u003dSmZ9XcTpMS4\"\u003eServiceWorker is coming, look busy\u003c/a\u003e talk (30min)\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7635529167330397808"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/blink/serviceworker/getting-started"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5321757110955595249"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5321757110955595249"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5321757110955595249"}],"author":[{"name":{"$t":"Dominic Cooney"},"email":{"$t":"dominicc@chromium.org"}}],"sites$pageName":{"$t":"getting-started"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"UCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6261796016295893248"},"published":{"$t":"2012-11-12T18:40:32.278Z"},"updated":{"$t":"2015-04-01T00:58:31.465Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-04-01T00:58:29.802Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Acer C7 Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction1\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eEntering\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-USB-Boot\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eUSB Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eLegacy Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003eLeaving\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Access-to-upgradable-cleanable-components\"\u003e\u003cstrong\u003e4.1.1 \u003c/strong\u003eAccess to upgradable/cleanable components\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Access-to-the-rest-of-the-machine\"\u003e\u003cstrong\u003e4.1.2 \u003c/strong\u003eAccess to the rest of the machine\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware-Write-Protect\"\u003e\u003cstrong\u003e4.1.3 \u003c/strong\u003eFirmware Write Protect\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"http://www.google.com/intl/en/chrome/devices/acer-c7-chromebook.html\"\u003eAcer C7 Chromebook\u003c/a\u003e that is interesting and/or useful t\u003cspan style\u003d\"font-size:10pt\"\u003eo software developers.  For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/span\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003eCPU: Intel \u003ca href\u003d\"http://en.wikipedia.org/wiki/Sandy_Bridge\" rel\u003d\"nofollow\"\u003eSandy Bridge\u003c/a\u003e Celeron (might vary on specific model)\u003c/li\u003e\u003cul\u003e\u003cli\u003eSome later models shipped \u003ca href\u003d\"http://en.wikipedia.org/wiki/Ivy_Bridge_(microarchitecture)\" rel\u003d\"nofollow\"\u003eIvy Bridge\u003c/a\u003e; those will use the parrot_ivb board\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eGPU: Intel \u003ca href\u003d\"http://en.wikipedia.org/wiki/Sandy_Bridge\" rel\u003d\"nofollow\"\u003eSandy Bridge\u003c/a\u003e Mobile\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e11.6\" 1366x768 16:9\u003c/li\u003e\r\n\u003cli\u003eHDMI port\u003c/li\u003e\r\n\u003cli\u003eVGA port\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRAM: 2 GiB or 4GiB DDR3 (might vary on specific model)\u003c/li\u003e\r\n\u003cli\u003eDisk: 320 GiB HD or 16 GiB SSD (might vary on specific model)\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eUSB expansion ports\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eNetworking\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi 802.11 a/b/g/n\u003c/li\u003e\r\n\u003cli\u003eDedicated Ethernet port\u003c/li\u003e\r\n\u003cli\u003eUSB ports can handle Ethernet dongles\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003ePower supply: 19V \u003cimg border\u003d\"0\" height\u003d\"5\" src\u003d\"http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices/direct-current.svg?attredirects\u003d0\u0026amp;d\u003d1\" /\u003e (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Direct_current\" rel\u003d\"nofollow\"\u003eDC\u003c/a\u003e) 2.15A \u003cimg height\u003d\"12\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1364850218094/chromium-os/developer-information-for-chrome-os-devices/center-positive-polarity.svg\" /\u003e (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Polarity_symbols\" rel\u003d\"nofollow\"\u003epositive polarity tip\u003c/a\u003e)\r\n\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eServo header\u003c/a\u003e: 1x50 header (now obsolete)\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eAn unrelated note: Holding just Refresh and poking the Power button hard-resets the machine without entering Recovery. That's occasionally useful, but use it with care - it doesn't sync the disk or shut down politely, so there's a nonzero chance of trashing the contents of your stateful partition.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Introduction1\" /\u003eIntroduction\u003c/h3\u003e\r\n\u003cp\u003eEnabling Developer mode is the first step to tinkering with your Chromebook. With Developer mode enabled you can do things like poke around on a command shell (as root if you want), install Chromium OS, or try other OS's. Note that Developer mode turns off some security features like verified boot and disabling the shell access. If you want to browse in a safer, more secure way, leave Developer mode turned OFF. Note: Switching between Developer and Normal (non-developer) modes will remove user accounts and their associated information from your Chromebook.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Entering\" /\u003eEntering\u003c/h3\u003e\r\n\u003cp\u003eOn this device, both the recovery button and the dev-switch have been virtualized. Our partners don't really like physical switches - they cost money, take up space on the motherboard, and require holes in the case.\u003c/p\u003e\r\n\u003cp\u003eTo invoke Recovery mode, you hold down the \u003cfont color\u003d\"#990000\"\u003eESC\u003c/font\u003e and \u003cfont color\u003d\"#990000\"\u003eRefresh\u003c/font\u003e (F3) keys and poke the \u003cfont color\u003d\"#990000\"\u003ePower\u003c/font\u003e button.\u003c/p\u003e\r\n\u003cp\u003eTo enter Dev-mode you first invoke Recovery, and at the Recovery screen press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e (there's no prompt - you have to know to do it). It will ask you to confirm, then reboot into dev-mode.\u003c/p\u003e\r\n\u003cp\u003eDev-mode works the same as always: It will show the scary boot screen and you need to press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e or wait 30 seconds to continue booting.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-USB-Boot\" /\u003eUSB Boot\u003c/h3\u003e\r\n\u003cp\u003eBy default, USB booting is disabled. Once you are in Dev-mode and have a root shell, you can run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo crossystem dev_boot_usb\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot from USB drives with Ctrl-U.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot\" /\u003eLegacy Boot\u003c/h3\u003e\r\n\u003cp\u003eSorry, but this device does not support a legacy BIOS mode. It predates the launch of that feature and it is not feasible to produce updates of devices in the field.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Leaving\" /\u003eLeaving\u003c/h3\u003e\r\n\u003cp\u003eTo leave Dev-mode and go back to normal mode, just follow the instructions at the scary boot screen. It will prompt you to confirm.\u003c/p\u003e\r\n\u003cp\u003eIf you want to leave Dev-mode programmatically, you can run \u003ccode\u003ecrossystem disable_dev_request\u003d1; reboot\u003c/code\u003e from a root shell. There's no way to enter Dev-mode programmatically, and just seeing the Recovery screen isn't enough - you have to use the three-finger salute which hard-resets the machine first. That's to prevent a remote attacker from tricking your machine into dev-mode without your knowledge.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e and \u003ca href\u003d\"http://www.denx.de/wiki/U-Boot\" rel\u003d\"nofollow\"\u003eDas U-Boot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-parrot-2685.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e and the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/u-boot/+/firmware-parrot-2685.B\"\u003eChromium OS u-boot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-parrot-2685.B\u003c/code\u003e branches.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center.  Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first. \u003cspan style\u003d\"font-size:10pt\"\u003eIf you just want to see what the inside looks like, gaze upon this (click for high res versions):\u003c/span\u003e\u003c/p\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin:5px auto 0px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook/acer-c7-bottom-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"221\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1359987259480/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook/acer-c7-bottom-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \r\n\u003cdiv style\u003d\"display:inline;text-align:center;margin:5px 0px 0px 10px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook/acer-c7-top-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"226\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1371937634459/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook/acer-c7-top-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cp\u003eHowever, we acknowledge that some people like to tinker.  So here's a quick guide to taking it apart.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Access-to-upgradable-cleanable-components\" /\u003eAccess to upgradable/cleanable components\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003eThis is very easy to do and gets you access to \u003cspan style\u003d\"font-size:10pt\"\u003eall the pieces you most likely care about:\u003c/span\u003e\u003c/p\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"277\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1358353208129/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook/acer-c7-case-bottom.jpg\" style\u003d\"font-size:10pt;display:inline;margin:5px 10px;float:right\" width\u003d\"400\" /\u003e\r\n\u003cul\u003e\u003cli\u003eThe hard drive is easy to remove \u0026amp; replace/upgrade\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e2.5\" SATA 2 or SATA 3 drives should work\u003c/li\u003e\r\n\u003cli\u003etry to get a 7mm tall one (9.5mm will fit, just sans padding)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eThe two memory slots are easy to access\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThe system uses 204-Pin DDR3 SO-DIMM laptop memory\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eThe wifi module is easily removable (one screw)\u003c/li\u003e\r\n\u003cli\u003eThe exhaust fan is easily removed (two screws) for cleaning\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eAnd here's the details (see image on right for more details):\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eGet a smallish phillips head screw driver -- all screws can be removed with just this\u003c/li\u003e\r\n\u003cli\u003eShut the system down and close the lid\u003c/li\u003e\r\n\u003cli\u003eFlip the laptop over so the bottom is facing up and the warranty seal is closest to you\u003c/li\u003e\r\n\u003cli\u003e(Step 1) Break the seal that says \"warranty is void if seal is broken\" -- be aware, you might void your warranty by breaking the seal :)\u003c/li\u003e\r\n\u003cli\u003e(Step 1) Remove the single screw under the seal\u003c/li\u003e\r\n\u003cli\u003e(Step 2) Remove the battery\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e(Step 2a) There is a slide near the edge of the battery in the upper right section -- put the tip of the screw driver into the divot and slide it to the right to unlock the battery\u003c/li\u003e\r\n\u003cli\u003e(Step 2b) While the battery is unlocked, pull it out\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e(Step 3) Place your thumbs on the bottom two feet and pull towards you\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eAlternatively, you can pull on the edge where the battery was\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eCheck out the high res picture above for overview.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Access-to-the-rest-of-the-machine\" /\u003eAccess to the rest of the machine\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eWhile it is possible to remove the motherboard entirely, there isn't much of a point. You can see a high res image of what it looks like above if you just want that.\u003cimg border\u003d\"0\" height\u003d\"222\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1358354575956/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook/acer-c7-bottom-screws.jpg\" style\u003d\"font-size:10pt;display:inline;margin:5px 10px;float:right\" width\u003d\"320\" /\u003e\u003c/p\u003e\r\n\u003cp\u003eIf you really want to remove it, then here's how:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eRemove the 18 screws holding it down (does not include the warranty screw)\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e4 screws: one next to each of the rubber feet\u003c/li\u003e\r\n\u003cli\u003e11 screws labeled M2x6 (including one on the cooling fan)\u003c/li\u003e\r\n\u003cli\u003e1 screw labeled M2x3 (near the memory module)\u003c/li\u003e\r\n\u003cli\u003e1 screw on the the cooling fan (kitty corner to the M2x6 one)\u003c/li\u003e\r\n\u003cli\u003e1 screw on the wireless module\u003c/li\u003e\r\n\u003cli\u003eYou do not have to remove other screws (like the ones around the cpu)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eThe top part of the case is now held to the bottom by plastic tabs around the edge\u003c/li\u003e\r\n\u003cli\u003eTurn the computer onto its side and slowly pry it apart\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eSwitch between the sides to slowly work it apart\u003c/li\u003e\r\n\u003cli\u003eYou can press on the center of the motherboard where the empty memory slot is to help\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Firmware-Write-Protect\" /\u003eFirmware Write Protect\u003c/h4\u003e\r\n\u003cp\u003eIt's a jumper next to the CPU under the black plastic. See the pictures above for more details.\u003c/p\u003e\r\n\u003cul /\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6261796016295893248"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6261796016295893248"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6261796016295893248"}],"author":[{"name":{"$t":"Bill Richardson"},"email":{"$t":"wfrichar@chromium.org"}}],"sites$pageName":{"$t":"acer-c7-chromebook"},"sites$revision":{"$t":"19"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1847460920542916204"},"published":{"$t":"2015-03-27T16:44:26.073Z"},"updated":{"$t":"2015-03-27T16:50:53.775Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-27T16:50:52.263Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"onc"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eSee \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/open-network-configuration\"\u003eOpen Network Configuration\u003c/a\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/onc"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1847460920542916204"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1847460920542916204"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1847460920542916204"}],"author":[{"name":{"$t":"Steven Bennetts"},"email":{"$t":"stevenjb@chromium.org"}}],"sites$pageName":{"$t":"onc"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"XSl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3227207961814526512"},"published":{"$t":"2010-04-26T16:07:43.801Z"},"updated":{"$t":"2015-03-26T17:25:47.825Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-26T17:25:47.824Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Reporting a Hang Bug"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eTo investigate problems when Chrome is frozen/locked-up/unresponsive, we generally need a dump of the affected processes.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eExactly how to do this depends on your operating system:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Windows\" /\u003eWindows\u003c/h2\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003ca href\u003d\"http://technet.microsoft.com/en-us/sysinternals/bb896653\" rel\u003d\"nofollow\"\u003eDownload Process Explorer from Microsoft\u003c/a\u003e. (This tool is like a more advanced version of the Task Manager; we will use it to create minidumps).\u003c/li\u003e\u003cli\u003eExtract and launch Process Explorer\u003c/li\u003e\u003cli\u003eRight click on the hung Chrome process, and choose \"Create Dump\" --\u0026gt; \"Create Minidump...\" (If you aren't sure which one is misbehaving, repeat this step for each Chrome process)\u003c/li\u003e\u003cli\u003eAttach the minidump file(s) to your bug report\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003ePlease note that minidump files can contain some information about your computer, including the path to where Chrome is installed.\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Mac\" /\u003eMac\u003c/h2\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eVerify you've turned crash reporting on. Go to the page \u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003echrome://settings/advanced using the address bar. Then verify that \u003c/span\u003e\u003cb\u003eAutomatically send usage statistics and crash reports to Google\u003c/b\u003e is checked.\u003c/li\u003e\u003cli\u003eOpen the Task Manager under the \u003cb\u003eWrench menu \u0026gt; Tools \u0026gt; Task Manager\u003c/b\u003e.\u003c/li\u003e\u003cli\u003eIf the columns at the top of the Task Manager window do not include \"Process ID\", then right-click on the table header and check the \"Process ID\" box.\u003c/li\u003e\u003cli\u003eNote the process ID of the hung tab.\u003c/li\u003e\u003cli\u003eKill the process in a way that causes it to print a crash dump:\u003c/li\u003e\u003c/ol\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eOpen a terminal window and \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt\"\u003ekill -ABRT \u003ci\u003e\u0026lt;ProcessID\u0026gt;\u003c/i\u003e\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e where \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt\"\u003e\u003ci\u003e\u0026lt;ProcessID\u0026gt;\u003c/i\u003e\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e is the one you noted above.  Copy and paste the crash ID dumped to the console into your bug\u003c/span\u003e:\u003c/li\u003e\u003cul\u003e\u003cli\u003eYou can additionally find the crash dump in \u003cspan style\u003d\"font-family:arial,sans-serif;font-size:small;white-space:pre-wrap\"\u003e\u003cfont color\u003d\"#38761D\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;white-space:normal;font-size:13px\"\u003e~/Library/Application Support/Google/Chrome/Crash Reports/\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Linux\" /\u003eLinux\u003c/h2\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eDepending on your sandboxing configuration and Chrome version, you may need to pass \"--allow-sandbox-debugging\" when starting Chrome (see \u003ca href\u003d\"http://crbug.com/169369\"\u003ethis bug\u003c/a\u003e).\u003c/li\u003e\u003cli\u003eVerify you've turned crash reporting on. Go to the page \u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003echrome://settings/advanced using the address bar. Then verify that \u003c/span\u003e\u003cb\u003eAutomatically send usage statistics and crash reports to Google\u003c/b\u003e is checked.\u003c/li\u003e\u003cli\u003eOpen the Task Manager under the \u003cb\u003eWrench menu \u0026gt; Tools \u0026gt; Task Manager\u003c/b\u003e.\u003c/li\u003e\u003cli\u003eIf the columns at the top of the Task Manager window do not include \"Process ID\", then right-click on the window and check the \"Process ID\" box.\u003c/li\u003e\u003cli\u003eNote the process ID of the hung tab.\u003c/li\u003e\u003cli\u003eKill the process in a way that causes it to print a crash dump:\u003c/li\u003e\u003c/ol\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eOpen a terminal window and \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt\"\u003ekill -SEGV \u003ci\u003e\u0026lt;ProcessID\u0026gt;\u003c/i\u003e\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e where \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt\"\u003e\u003ci\u003e\u0026lt;ProcessID\u0026gt;\u003c/i\u003e\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e is the one you noted above.  Copy and paste the crash ID dumped to the console into your bug:\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eYou can find the crash dump in your \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt\"\u003e~/.xsession-errors\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e file (assuming you didn't launch Chromium from a terminal yourself)\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2480943774340680129"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/for-testers/bug-reporting-guidelines/hanging-tabs"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3227207961814526512"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3227207961814526512"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3227207961814526512"}],"author":[{}],"sites$pageName":{"$t":"hanging-tabs"},"sites$revision":{"$t":"24"}},{"gd$etag":"\"Xil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4561865247447219566"},"published":{"$t":"2013-09-11T22:56:22.503Z"},"updated":{"$t":"2015-03-26T16:00:02.469Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-26T16:00:01.125Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"FrameHandle"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cb\u003eThis design document is out of date.\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003eBlink Frames are now implemented using an inheritance relationship, where blink::Frame is a base class for blink::LocalFrame and blink::RemoteFrame. They are now fully implemented so this documentation will not be updated.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eDoc: \u003ca href\u003d\"https://docs.google.com/a/chromium.org/document/edit?id\u003d1PeSpryRsXlLxHU58GOa0s67kuKaQeGitmM0iWS02CvU\" style\u003d\"background-color:transparent;font-size:10pt\"\u003ehttps://docs.google.com/a/chromium.org/document/edit?id\u003d1PeSpryRsXlLxHU58GOa0s67kuKaQeGitmM0iWS02CvU\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eFrameHandle\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-object-title\" style\u003d\"display:none;\"\u003eFrameHandle\u003c/div\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-writely\"\u003e\u003ciframe src\u003d\"http://docs.google.com/document/preview?hgd\u003d1\u0026amp;id\u003d1PeSpryRsXlLxHU58GOa0s67kuKaQeGitmM0iWS02CvU\" width\u003d\"100%\" height\u003d\"600\" title\u003d\"FrameHandle\" frameborder\u003d\"0\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eDiagram: \u003cspan style\u003d\"color:rgb(0,102,204);text-decoration:underline;background-color:transparent;font-size:10pt\"\u003ehttps://docs.google.com/a/chromium.org/drawings/d/1sqOb8DCNy7wlPMCp9oPyd981wBsYfvy4SsRZD4_HYos/view\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed\" style\u003d\"width:720px;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eFrameHandle\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-object-title\" style\u003d\"display:none;\"\u003eFrameHandle\u003c/div\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-sketchy\"\u003e\u003ciframe src\u003d\"http://docs.google.com/drawings/d/1sqOb8DCNy7wlPMCp9oPyd981wBsYfvy4SsRZD4_HYos/preview?h\u003d1280\u0026amp;hl\u003den\u0026amp;w\u003d720\" width\u003d\"720\" height\u003d\"1280\" title\u003d\"FrameHandle\" frameborder\u003d\"0\" id\u003d\"889072466\" allowfullscreen\u003d\"true\" mozallowfullscreen\u003d\"true\" webkitallowfullscreen\u003d\"true\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2708308332133640550"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/oop-iframes/framehandle"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4561865247447219566"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4561865247447219566"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4561865247447219566"}],"author":[{"name":{"$t":"Daniel Cheng"},"email":{"$t":"dcheng@chromium.org"}}],"sites$pageName":{"$t":"framehandle"},"sites$revision":{"$t":"17"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/881637625676757546"},"published":{"$t":"2014-04-17T20:02:50.526Z"},"updated":{"$t":"2015-03-25T23:52:42.695Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-25T23:52:42.695Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"System Tray"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h2\u003e\r\n\u003cdiv\u003e\r\nThe system tray is part of the Ash status area. It displays system status and settings, and expands into a menu with more information and settings controls. Each system tray item may have any subset of the 4 view types:\r\n\u003cul\u003e\r\n\u003cli\u003e\u003cb\u003eTray view.\u003c/b\u003e This is the view that shows in the status area, such as the clock or the Wi-Fi indicator image.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eDefault view.\u003c/b\u003e This is the view that appears in the list when the tray bubble is opened.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eDetailed view.\u003c/b\u003e This view appears by itself. If the tray bubble is already open, the detailed view is displayed within the existing window for the tray bubble.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eNotification view.\u003c/b\u003e Obsolete. The SMS notification is shown as a notification view. Other tray items use the message center or their detailed view to show notifications.\u003c/li\u003e\r\n\u003c/ul\u003e\r\nThis document summarizes the behavior of each system tray item. Some system tray items are only available while logged in.\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-List-of-system-tray-items\" /\u003eList of system tray items\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003ctable cellpadding\u003d\"0\" cellspacing\u003d\"0\" dir\u003d\"ltr\" style\u003d\"table-layout:fixed;font-family:arial,sans,sans-serif\"\u003e\r\n\u003ccolgroup\u003e\r\n\u003ccol width\u003d\"68\" /\u003e\r\n\u003ccol width\u003d\"92\" /\u003e\r\n\u003ccol width\u003d\"171\" /\u003e\r\n\u003ccol width\u003d\"150\" /\u003e\r\n\u003ccol width\u003d\"98\" /\u003e\r\n\u003ccol width\u003d\"70\" /\u003e\r\n\u003ccol width\u003d\"94\" /\u003e\r\n\u003ccol width\u003d\"94\" /\u003e\r\n\u003ccol width\u003d\"102\" /\u003e\r\n\u003ccol width\u003d\"158\" /\u003e\u003c/colgroup\u003e\r\n\u003ctbody\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-weight:bold;border:1px solid rgb(204,204,204);width:156px;height:45px\"\u003eSystem tray item\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);width:85px;height:45px\"\u003eTray view\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);width:198px;height:45px\"\u003eDefault view\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);width:198px;height:45px\"\u003eDetailed view\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);width:144px;height:45px\"\u003eNotifications\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);width:72px;height:45px\"\u003eChrome OS only\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204);width:118px;height:45px\"\u003eVisible in sign-in screen, lock screen, OOBE\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eScreenCaptureTrayItem\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eMessage center\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eNo?\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eScreenShareTrayItem\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eMessage center\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eNo?\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:60px\"\u003e\u003cb\u003eTrayAccessibility\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:60px\"\u003eWhen accessible option is enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:60px\"\u003eYes, unless disabled in settings\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:60px\"\u003eYes (from default view)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:60px\"\u003eCustom popup\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:60px\"\u003eNo (Windows, Linux)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:60px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayAudio\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eWhen muted\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003ePops up when volume changes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eDetailed view popup\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003e\u003cbr /\u003e\r\n\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayAudioChromeOs\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eWhen muted\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003ePops up when volume changes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eDetailed view popup\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayAudioWin\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eNo (Windows)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eN/A\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:16px\"\u003e\u003cb\u003eTrayBluetooth\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:16px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:16px\"\u003eYes (from default view)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:16px\"\u003eNo (Linux)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:16px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTrayBrightness\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eIn TouchView\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003ePops up when brightness changes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eDetailed view popup\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eYes\r\n\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTrayCapsLock\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eWhen enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eWhen enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003ePops up when caps lock is enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eDetailed view popup\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTrayDate\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eNo (Windows, Linux)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayDisplay\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eWhen display changes or is mirrored, extended or docked\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eMessage center\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayDrive\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eFor the owner when waiting on Drive\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes (from default view)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eNo (Linux)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayEnterprise\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eWhen device is managed (non-public user)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\r\n\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTrayIME\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eIf multiple input methods are enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eIf multiple input methods are enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eYes (from default view)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eNo (Linux)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayLocallyManagedUser\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eFor locally managed user\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eMessage center\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:60px\"\u003e\u003cb\u003eTrayNetwork\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:60px\"\u003eSometimes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:60px\"\u003eYes, once initialized\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:60px\"\u003eYes (from default view)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:60px\"\u003eDetailed view popup or message center\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:60px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:60px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayPower\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eIf battery present\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo (part of TraySettings)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eMessage center\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:16px\"\u003e\u003cb\u003eTrayRotationLock\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:16px\"\u003eIn TouchView\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:16px\"\u003eIn TouchView\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:16px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:16px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTraySessionLengthLimit\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eWhen limited\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eMessage center\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:16px\"\u003e\u003cb\u003eTraySettings\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:16px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:16px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:16px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:16px\"\u003eSometimes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTraySms\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eWhen messages available\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eWhen messages available\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eWhen messages available\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eNotification view\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003e?\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayTracing\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eWhen tracing is enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eWhen tracing is enabled\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTrayUpdate\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eWhen upgrade is available\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eWhen upgrade is available\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eYes (pops up periodically)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eDetailed view popup\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eNo (Windows, Linux)\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:45px\"\u003e\u003cb\u003eTrayUser\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:45px\"\u003eSometimes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eYes\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:45px\"\u003eYes (new account management)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:45px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:45px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:45px\"\u003eNo\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayUserSeparator\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eWhen multiple users logged in\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eNo\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\r\n\r\n\r\n\u003ctr style\u003d\"height:17px\"\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);width:156px;height:30px\"\u003e\u003cb\u003eTrayVPN\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:85px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eIf VPN configured\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:198px;height:30px\"\u003eYes (from default view)\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:144px;height:30px\"\u003eNo\u003c/td\u003e\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:72px;height:30px\"\u003eYes\u003c/td\u003e\r\n\r\n\r\n\r\n\r\n\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);width:118px;height:30px\"\u003eLock screen\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\r\n\r\n\r\n\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2680325264819182270"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/aura/system-tray"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/881637625676757546"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/881637625676757546"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/881637625676757546"}],"author":[{"name":{"$t":"Michael Giuffrida"},"email":{"$t":"michaelpg@chromium.org"}}],"sites$pageName":{"$t":"system-tray"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5238429020651431126"},"published":{"$t":"2015-03-25T17:38:41.502Z"},"updated":{"$t":"2015-03-25T18:19:33.099Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-25T18:19:31.377Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Profiling Blink using Flame Graphs"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"margin:0;padding:0;max-width:100ex;text-align:justify\"\u003e\r\n\u003cp style\u003d\"margin-top:0\"\u003eQuick how to explaining how to profile Blink tests on Linux and analyze the results using flame graphs.\u003c/p\u003e\r\n\r\n\u003cimg alt\u003d\"Example flame graph.\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1427307142334/developers/profiling-flame-graphs/flamegraph.png\" /\u003e\u003cbr /\u003e\r\n\u003ca href\u003d\"https://blink.gs/images/line-layout-flame-graph.svg\" rel\u003d\"nofollow\"\u003eInteractive Example\u003c/a\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Prerequisites\" /\u003ePrerequisites\u003c/h2\u003e\r\n\u003cul\u003e\r\n \u003cli\u003eperf - available in the package linux-tools on Ubuntu.\u003c/li\u003e\r\n \u003cli\u003eFlameGraph - \u003ca href\u003d\"https://github.com/brendangregg/FlameGraph/archive/master.zip\" rel\u003d\"nofollow\"\u003eFlameGraph.zip\u003c/a\u003e or see \u003ca href\u003d\"https://github.com/brendangregg/FlameGraph\" rel\u003d\"nofollow\"\u003egithub page\u003c/a\u003e.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Instructions\" /\u003eInstructions\u003c/h2\u003e\r\n\r\n\u003cp\u003e\r\n To get profiling data one needs to build chromium and/or content_shell with \u003ccode\u003eGYP_DEFINE+\u003d\"profiling\u003d1\"\u003c/code\u003e \u003c/p\u003e\r\n\r\n\u003cp\u003e\r\n The basic strategy is to do the following:\r\n\u003c/p\u003e\r\n\u003col\u003e\r\n \u003cli\u003eBuild with \u003ccode\u003eGYP_DEFINE+\u003d\"profiling\u003d1\"\u003c/code\u003e\u003c/li\u003e\r\n \u003cli\u003eRecord using \u003ccode\u003eperf record\u003c/code\u003e.\r\n \u003c/li\u003e\r\n\u003cli\u003eCollapse stacks using \u003ccode\u003estackcollapse-perf.pl\u003c/code\u003e.\r\n \u003c/li\u003e\r\n\u003cli\u003eGenerate flame graph using \u003ccode\u003eflamegraph.pl\u003c/code\u003e.\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Profiling-a-Performance-Test\" /\u003eProfiling a Performance Test\u003c/h2\u003e\r\n\u003cp\u003e\r\n For example, to profile and generate a visualization for the Blink \u003ccode\u003eLayout/line-layout.html\u003c/code\u003e \r\n performance tests the following command sequence could be used.\r\n This assumes that the FlameGraph software from above is in the \u003ccode\u003ePATH\u003c/code\u003e.\r\n\u003c/p\u003e\r\n\r\n\u003cpre\u003e GYP_DEFINES+\u003d\"profiling\u003d1\" gclient runhooks\r\n ninja -C out/Release blink_tests\r\n perf record -F \u003cabbr title\u003d\"frequency in Hz\"\u003e500\u003c/abbr\u003e -g -q -- ./out/Release/content_shell \\\r\n --dump-render-tree `pwd`/third_party/WebKit/PerformanceTests/Layout/line-layout.html\r\n perf script | stackcollapse-perf.pl | flamegraph.pl \u0026gt; /tmp/flamegraph.svg\r\n\u003c/pre\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Analyzing-the-Results\" /\u003eAnalyzing the Results\u003c/h2\u003e\r\n\u003cp\u003e\r\n The generated SVG file is an interactive document that can be opened in Chrome (or any other browser). Clicking a stack frame will \"zoom in\" to that frame. See the \u003ca href\u003d\"http://www.brendangregg.com/flamegraphs.html\" rel\u003d\"nofollow\"\u003eFlame Graphs\u003c/a\u003e home page for further information and other use cases.\r\n\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Further-Reading\" /\u003eFurther Reading\u003c/h2\u003e\r\n\u003cul\u003e\r\n \u003cli\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/wiki/LinuxProfiling\"\u003eChromium profiling on linux\u003c/a\u003e.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/profiling-flame-graphs"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5238429020651431126"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5238429020651431126"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5238429020651431126"}],"author":[{"email":{"$t":"eae@chromium.org"}}],"sites$pageName":{"$t":"profiling-flame-graphs"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8271247905708167355"},"published":{"$t":"2015-03-25T18:09:58.019Z"},"updated":{"$t":"2015-03-25T18:12:22.334Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-25T18:12:22.308Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"flamegraph.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8271247905708167355"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5238429020651431126"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/profiling-flame-graphs/flamegraph.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8271247905708167355"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8271247905708167355"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8271247905708167355"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8271247905708167355"}],"author":[{"email":{"$t":"eae@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"Wil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6732688660809667187"},"published":{"$t":"2011-12-02T15:12:06.193Z"},"updated":{"$t":"2015-03-25T17:11:09.742Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-25T16:17:43.387Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Network Portal Detection"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Shill-Service-State-Machine\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eShill Service State Machine\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Reverse-Path-Filtering\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eReverse Path Filtering\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Shill-Implementation\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eShill Implementation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Interpretation-of-Portal-State\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eInterpretation of Portal State\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Web-Proxies\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eWeb Proxies\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Future-Ideas\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eFuture Ideas\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eShill, the connection manager for Chromium OS, attempts to detect services that are within a captive portal whenever a service transitions to the ready state.  This determination of being in a\u003ci\u003e captive portal\u003c/i\u003e or being \u003ci\u003eonline\u003c/i\u003e is done by attempting to retrieve the webpage \u003cfont face\u003d\"'courier new', monospace\"\u003ehttp://clients3.google.com/generate_204\u003c/font\u003e.  This well known URL is known to return an empty page with an HTTP status 204.  If for any reason the web page is not returned, or an HTTP response other than 204 is received, then shill marks the service as being in the \u003ci\u003eportal\u003c/i\u003e state.\u003c/p\u003e\r\n\u003cp\u003eMany, or perhaps most, captive portals found in Hotels, Coffee Shops, Airports, etc, either run their own DNS server which returns IP address for all queries which point to their webserver, or they intercept all HTTP web traffic and return a 302 (redirect) response.  The captive portal detection works very reliably with these types of portal to indicate that the service is not fully online.\u003c/p\u003e\r\n\u003cp\u003eOther captive portals, sometimes run by cellular carriers, provide absolutely no IP connectivity other than to their own servers, but they use a standard DNS server and do not intercept HTTP requests.  When a ChromeBook connects to this type of network, the HTTP requests fail because the TCP connection to \u003cfont face\u003d\"'courier new', monospace\"\u003eclients3.google.com\u003c/font\u003e can never be established.  The portal code tries multiple times for up to 10 seconds to connect to \u003cfont face\u003d\"'courier new', monospace\"\u003eclients3.google.com\u003c/font\u003e.  If it cannot connect it marks the service as being in a captive portal.  This determination is somewhat unreliable because very high latency connections, lossy connections and other network issues can also result in failure to connect to \u003cfont face\u003d\"'courier new', monospace\"\u003eclients3.google.com\u003c/font\u003e.  All of these are indicative of a network that is not fully functional, but they do not necessarily indicate that the machine is stuck in a \u003ci\u003ecaptive portal.\u003c/i\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Shill-Service-State-Machine\" /\u003eShill Service State Machine\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\r\n\u003cdiv style\u003d\"display:block;margin-right:auto;margin-left:auto;text-align:center\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/network-portal-detection/FlimflamServiceStateMachine.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Flimflam service state machine\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1326298284439/chromium-os/chromiumos-design-docs/network-portal-detection/FlimflamServiceStateMachine.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Reverse-Path-Filtering\" /\u003eReverse Path Filtering\u003c/h3\u003e\r\n\u003cp\u003eBy default ChromeOS enables \u003ca href\u003d\"http://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.kernel.rpf.html\" rel\u003d\"nofollow\"\u003ereverse path filtering\u003c/a\u003e in the kernel which drops packets received over a network interface inconsistent with the outbound routing tables.  This can present a problem when trying to determine portal state when connected to multiple networks (WiFi, Wired Ethernet and/or a Mobile Broadband connection).  To avoid dropped packets, shill disables reverse path filtering globally and on a per device basis while it is running the portal detection code.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Shill-Implementation\" /\u003eShill Implementation\u003c/h3\u003e\r\n\u003cp\u003eshill attempts to determine the portal state whenever a service transitions to the \u003ci\u003eready\u003c/i\u003e state.  It does the determination using libcurl.  Several options are set:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003elibcurl is instructed not to cache DNS entries, and not to allow re-use of HTTP connections\u003c/li\u003e\r\n\u003cli\u003elibcurl is given a 10 second timeout for connection and for the entire transaction.\u003c/li\u003e\r\n\u003cli\u003elibcurl is told to bind to a specific interface so all traffic is done over that interface\u003c/li\u003e\r\n\u003cli\u003elibcurl is explicitly told which name servers to use for name resolution\u003c/li\u003e\r\n\u003cli\u003ereverse path filtering is disabled (see above).\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003ePortal detection can be enabled or disabled on a per service basis, or if that is not set (set to AUTO), the determination is done based on the default for the technology.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Interpretation-of-Portal-State\" /\u003eInterpretation of Portal State\u003c/h3\u003e\r\n\u003cp\u003eChrome and shill use portal state for a variety of reasons.\u003c/p\u003e\r\n\u003cp\u003eFor prioritizing connections shill always prioritizes an \u003ci\u003eonline \u003c/i\u003econnection over one in a \u003ci\u003eportal\u003c/i\u003e state.  To the extent that connections using a web proxy are never marked as \u003ci\u003eportal \u003c/i\u003ebut instead immediately marked as \u003ci\u003eonline \u003c/i\u003ethis inhibits shill's ability to choose the best connection/service.\u003c/p\u003e\r\n\u003cp\u003eFor cellular connections, and especially for Verizon, Chrome uses portal state to determine when to put up \u003ci\u003etoast\u003c/i\u003e which will prompt the user to buy more data.  It also controls the presence of a 'buy data' button on the network settings/information tabs for the Verizon Wireless service.\u003c/p\u003e\r\n\u003cp\u003eWhen at the OOBE pages and the login screen, Chrome uses the portal state to prompt the user to check the network connection (more details needed from the Chrome team).\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Web-Proxies\" /\u003eWeb Proxies\u003c/h3\u003e\r\n\u003cp\u003eWeb proxies present multiple problems for portal state determination.  libcurl supports forwarding requests via a proxy, but this can only be done if the IP address of the proxy is known.  Shill does not currently know the IP address of the web proxy, nor does it have the ability to evaluate the URL against the JavaScript code that determines if the proxy should be used.\u003c/p\u003e\r\n\u003cp\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eSeveral services (e.g. auto update, etc) use Chrome as the engine to fetch URLs, or use Chrome to evaluate the URL and find out which, if any, proxy to use.  This seems like an appealing solution, but, knowing the proxy is insufficient, because one might also need to authenticate to the proxy.  It is unclear if Chrome exposes the proxy authentication information.  I also do not believe that Chrome can proper evaluate a URL relative to the proxy settings on a per interface basis.  Chrome almost certainly uses the default connection and the proxy settings for the default connection when doing HTTP requests and when evaluating a URL against the JavaScript configuration.\u003c/span\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Future-Ideas\" /\u003eFuture Ideas\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eImprove Chrome to be able to do what libcurl does --- route http requests via a specific interface and use the DNS servers associated with that interface.\u003c/li\u003e\r\n\u003cli\u003eImprove Chrome so that it can authenticate to two different proxies on two different interfaces simultaneously.\u003c/li\u003e\r\n\u003cli\u003eImprove Chrome so that it can figure out automatic proxy configuration based on DNS lookup of wpad over different names on different interfaces.  (etc....)\u003c/li\u003e\r\n\u003cli\u003eHave the ChromeOS connection manager ask Chrome to fetch the URL instead of libcurl.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eOr\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eDo much of the above, but have Chrome return proxy authentication as well as IP address for a given URL, so that shill can pass the proxy information to libcurl (or implement it all ourselves in shill).\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/network-portal-detection"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6732688660809667187"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6732688660809667187"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6732688660809667187"}],"author":[{}],"sites$pageName":{"$t":"network-portal-detection"},"sites$revision":{"$t":"13"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8155460386682143596"},"published":{"$t":"2015-03-20T23:16:20.599Z"},"updated":{"$t":"2015-03-24T18:22:15.765Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-24T18:22:15.748Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Local vs Remote Frame diagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8155460386682143596"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2708308332133640550"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/oop-iframes/Local%20vs%20Remote%20Frame%20diagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8155460386682143596"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8155460386682143596"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8155460386682143596"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8155460386682143596"}],"author":[{"name":{"$t":"Charles Reis"},"email":{"$t":"creis@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5976851555349832998"},"published":{"$t":"2015-03-24T18:17:31.936Z"},"updated":{"$t":"2015-03-24T18:17:31.973Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-24T18:17:31.936Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2015-03-24 11:16:39.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5976851555349832998"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4431931993782345843"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/submitting-a-performance-bug/Screenshot%20from%202015-03-24%2011:16:39.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5976851555349832998"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5976851555349832998"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5976851555349832998"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5976851555349832998"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5478605515991813275"},"published":{"$t":"2015-03-16T15:32:31.533Z"},"updated":{"$t":"2015-03-20T16:10:28.703Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-20T16:10:27.339Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Video Capture"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eLast updated March 2015. Contributor: mcasas@\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h3\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003eThere are several components allowing for Video Capture in Chrome\u003c/div\u003e\u003cdiv\u003e\u003cul style\u003d\"font-size:13.3333330154419px\"\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003ethe Browser-side classes\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003ethe common Render infrastructure supporting all MediaStream use cases\u003c/span\u003e\u003c/li\u003e\u003cli\u003ethe local \u003cspan style\u003d\"font-size:13.3333330154419px\"\u003e\u0026lt;video\u0026gt; \u003c/span\u003eplayback and/or Jingle/WebRtc PeerConnection implementation.\u003c/li\u003e\u003c/ul\u003eAt the highest level, both Video and Audio \u003cspan style\u003d\"font-size:13.3333330154419px\"\u003ecapture is abstracted as a \u003c/span\u003e\u003ca href\u003d\"http://w3c.github.io/mediacapture-main/getusermedia.html\" style\u003d\"font-size:13.3333330154419px\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eMediaStream\u003c/a\u003e; this JS entity is created via calls to\u003cspan style\u003d\"font-size:13.3333330154419px\"\u003e \u003c/span\u003e\u003ca href\u003d\"http://www.html5rocks.com/en/tutorials/getusermedia/intro/#toc-gettingstarted\" style\u003d\"font-size:13.3333330154419px\" target\u003d\"_blank\"\u003eGetUserMedia()\u003c/a\u003e with the appropriate bag of parameters. What happens under the hood and what classes do what is the topic of this document. I'll speak about Video Capture although some concepts are interchangeable with Audio. I'll speak of\u003cspan style\u003d\"font-size:13.3333330154419px\"\u003e WebCam/Camera but the same reasoning applies to Video Digitizers, Virtual WebCams etc.\u003c/span\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Browser\" /\u003eBrowser\u003c/h3\u003e\u003cdiv\u003eIn the Cr sandbox model, all of what pertains to using hardware is abstracted in the Browser process, to which Render clients direct requests via IPC mechanisms, and Video Capture is no different. \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:inline;float:left;margin:5px 10px 0px 0px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/video-capture/VideoCaptureBrowserClasses.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"253\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1426527010123/developers/design-documents/video-capture/VideoCaptureBrowserClasses.jpg\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003eThe goal of this set of classes is to enumerate, open and close devices for capture, process captured frames, and keep accountancy of underlying resources. \u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eAt the Browser level there should be no device-specific code, that is, no non-singletons, created before the user first tries to enumerate or use any kind of capture (Video or Audio) device -- and that's the reason why \"Video Capture Device Capabilities\" under chrome://media-internals is empty before actually using any capture device. \u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eLet's have a look at the diagram. In the early Chrome startup times there'd be just one class, \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/renderer_host/media/media_stream_manager.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dmediastreammanager\u0026amp;l\u003d64\" target\u003d\"_blank\"\u003eMediaStreamManager\u003c/a\u003e (MSM) sitting lonely on the upper left corner. \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eMSM is a singleton class created and owned by BrowserMainLoop on UI thread, using a bunch of \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#search/\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dcontent/browser/renderer_host/media/media_stream_*\" target\u003d\"_blank\"\u003eMediaStream*\u003c/a\u003e classes to have conversations over IPC and to request the user for permissions (MediaStreamUI*). MS* classes deal with both Audio and Video.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px\"\u003eMSM creates on construction two other important singletons, namely the ref-counted \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/renderer_host/media/video_capture_manager.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dvideocapturemanager\" target\u003d\"_blank\"\u003eVideoCaptureManager\u003c/a\u003e (VCM) and the associated \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/media/video/capture/video_capture_device_factory.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dVideoCaptureDeviceFactory\" target\u003d\"_blank\"\u003eVideoCaptureDeviceFactory\u003c/a\u003e (VCDF). VCDFactory is used to enumerated Device names and their capabilities, if they have any, and to instantiate VCDevices. There's one implementation per-platform and there are a few available:\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003ePlatform specific: Linux/CrOS (based on \u003ca href\u003d\"http://linuxtv.org/downloads/v4l-dvb-apis/index.html\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eV4L2\u003c/a\u003e API), Mac (both \u003ca href\u003d\"https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/QTKitApplicationProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008156-CH1-SW1\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eQTKit\u003c/a\u003e and \u003ca href\u003d\"https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eAVFoundation\u003c/a\u003e APIs), Windows (both \u003ca href\u003d\"https://msdn.microsoft.com/en-us/library/windows/desktop/dd375454%28v\u003dvs.85%29.aspx\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eDirectShow\u003c/a\u003e and \u003ca href\u003d\"https://msdn.microsoft.com/en-us/library/windows/desktop/ms694197%28v\u003dvs.85%29.aspx\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eMedia Foundation\u003c/a\u003e APIs) and Android (\u003ca href\u003d\"http://developer.android.com/reference/android/hardware/Camera.html\" target\u003d\"_blank\"\u003eCamera\u003c/a\u003e and \u003ca href\u003d\"http://developer.android.com/reference/android/hardware/camera2/package-summary.html\" target\u003d\"_blank\"\u003eCamera2\u003c/a\u003e APIs).\u003c/li\u003e\u003cli\u003eDebug/Test devices: \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/media/video/capture/fake_video_capture_device.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dfakevideocapturedevice\u0026amp;l\u003d21\" target\u003d\"_blank\"\u003eFakeVCD\u003c/a\u003e and \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/media/video/capture/file_video_capture_device.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;rcl\u003d1426491802\u0026amp;l\u003d26\" target\u003d\"_blank\"\u003eFileVCD\u003c/a\u003e. FakeVCD produces a stream with a \u003cspan style\u003d\"font-size:13.3333330154419px\"\u003erolling PacMan over a green canvas, while FileVCD plays uncompressed Y4M files.\u003c/span\u003e\u003c/li\u003e\u003cli\u003eOther captures: Desktop and Tab (Web contents) Capture.\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eVCM manages the lifetime of pairs \u0026lt;\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/renderer_host/media/video_capture_controller.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dvideocapturecontroller\" target\u003d\"_blank\"\u003eVideoCaptureController\u003c/a\u003e, \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/media/video/capture/video_capture_device.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dvideocapturedevice\u0026amp;l\u003d29\" target\u003d\"_blank\"\u003eVideoCaptureDevice\u003c/a\u003e\u0026gt;. VideoCaptureDevices (VCD) are adaptation layers between whichever infrastructure is provided by the OS for Video Capture and VideoCaptureController (VCC), whose mission is to bridge captured frames towards Render clients through the IPC.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eVCC interacts with the Render side code via a list of VideoCaptureHosts (VCH). VCH is a dual citizenship bridge between commands coming from Render to VCM (\u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/common/media/video_capture_messages.h\u0026amp;cl\u003dGROK\u0026amp;ct\u003dxref_jump_to_def\u0026amp;l\u003d91\u0026amp;gsn\u003dVideoCaptureHostMsg_Start\" style\u003d\"font-size:10pt;background-color:transparent\"\u003eVideoCaptureHostMsg_Start\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e and relatives) and those flowing from VCC towards Renderer. There are as many VCHosts as Render clients and they are created by RenderProcessHostImpl, another high level entity.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eLarge data chunks cannot be passed through the IPC pipes, so a Shared Memory mechanism is implemented in \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/renderer_host/media/video_capture_buffer_pool.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dvideocapturebufferpool\u0026amp;l\u003d46\" target\u003d\"_blank\"\u003eVideoCaptureBufferPool\u003c/a\u003e (VCBP -- not in the diagram, lives inside VCC). These \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eShMem-based \"Buffers\", as they are confusingly called, are allocated on demand and reserved for Producer or Consumers. \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eVCC keeps accountancy of those and recycles them when all clients have sent the \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/renderer_host/media/video_capture_host.cc\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;l\u003d228\" style\u003d\"font-size:13.3333330154419px;background-color:transparent\" target\u003d\"_blank\"\u003ecorresponding release message\u003c/a\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003e. \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eVideoFrames do not understand Buffers from this Pool so VCC has to keep count of them and recycle its uses via, again, IPC. \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eIt's relatively common that the Capture Devices do not provide exactly what the Render side requests or needs, hence an adaptation layer is inserted between VCC and VCD: \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/renderer_host/media/video_capture_device_client.h\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;q\u003dvideocapturedeviceclient\" target\u003d\"_blank\"\u003eVideoCaptureDeviceClient\u003c/a\u003e. VCDClient adapts sizes, applies rotations and otherwise converts the incoming pixel format to YUV420, which is the global transport pixel format. The output of such conversion rig is a ref-counted VideoFrame, which is the generic video transport class. \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eThe totality of VCDs assume a synchronous capture callback, hence VCDC copies/converts the captured buffer onto the ShMem allocated as a \"Buffer\". This VideoFrame-Buffer couple is then replicated to each VCHost on VCController. \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:13.3333330154419px\"\u003e(For the curiou\u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003es, IPC listener classes derive from BrowserMessageFilter).\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eDevice Monitoring?\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eCommon Render Infra\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eLocal \u0026lt;video\u0026gt; Playback\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eRemote WebRTC/Jingle encode and send\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/video-capture"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5478605515991813275"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5478605515991813275"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5478605515991813275"}],"author":[{"name":{"$t":"Miguel Casas-Sanchez"},"email":{"$t":"mcasas@chromium.org"}}],"sites$pageName":{"$t":"video-capture"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3482802397342084043"},"published":{"$t":"2015-03-20T13:52:41.039Z"},"updated":{"$t":"2015-03-20T14:41:40.693Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-20T14:38:27.611Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Preconnect"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cb\u003e\u003cfont size\u003d\"5\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOverview\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Implementation-Notes\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eImplementation Notes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Connection-Pools-not-all-connections-are-the-same-\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eConnection Pools (not all connections are the same)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Preconnect-Connection-Pool-Selection-Heuristic-proposed-\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003ePreconnect Connection Pool Selection Heuristic (proposed)\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/b\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003e\u003cb\u003e\u003cfont size\u003d\"5\"\u003eOverview\u003c/font\u003e\u003c/b\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cp\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003eThe networking stack implements the blink interface for the \u003ca href\u003d\"http://www.w3.org/TR/resource-hints/#preconnect\" rel\u003d\"nofollow\"\u003eW3C Resource Hints preconnect specification\u003c/a\u003e to allow site developers to request connections to servers in anticipation of future requests.  The predominant use cases are:\u003c/font\u003e\u003c/p\u003e\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003esub-resources for the current page that the preload scanner is not capable of identifying.  This can include resources discovered by styles being applied (background images, fonts) as well as resources initiated by scripts (analytics beacons, ads domains, etc).\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003eTop-level domains used in future navigations.  For example, clinking on a link to an url shortener or click tracker that then redirects to the actual page.  If the page knows the resulting final destination it can start initiating the connection in parallel with the navigation to the redirector.\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d450682\"\u003eIssue 450682\u003c/a\u003e tracks the implementation as well as issues that came up during implementation and experimentation.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Implementation-Notes\" /\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003eImplementation Notes\u003c/font\u003e\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Connection-Pools-not-all-connections-are-the-same-\" /\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003eConnection Pools (not all connections are the same)\u003c/font\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003eChrome maintains separate connection pools for the various different protocols (http, https, ftp, etc).  Additionally, separate connection pools are managed for connections where cookies can be transmitted and connections where they can not in order to prevent tracking of users when a request is determined to be private (when blocking cookies to third-party domains for example).  The determination of which connection pool a request will use is made at request time and depends on the context in which it is being made.  Top-level navigations go in the cookie-allowed pool while sub-resource requests get assigned a pool based on the domain of the request, the domain of the page and the user's privacy settings.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-family:verdana,sans-serif;font-size:13.3333330154419px;background-color:transparent\"\u003eConnections can not move from one pool to another so the determination of which pool a connection will be assigned to needs to be made at the time when the connection is being established.  In the case of TLS connections, the cost of not using a preconnected connection can be quite high, particularly on mobile devices with limited resources.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:verdana,sans-serif;font-size:13.3333330154419px;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:verdana,sans-serif;font-size:13.3333330154419px;background-color:transparent\"\u003eThe initial implementation for preconnect did not take private mode into account and all connections were pre-connected in the cookies-allowed connection pool leading to \u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d468005\"\u003esituations\u003c/a\u003e where the preconnected connection was not leveraged for the future request.\u003c/span\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Preconnect-Connection-Pool-Selection-Heuristic-proposed-\" /\u003e\u003cspan style\u003d\"font-family:verdana,sans-serif;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003ePreconnect Connection Pool Selection Heuristic (proposed)\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003eThe two different use cases for preconnect require different treatment for determining which connection pool a connection should belong to.  In the case of a sub-resource request the document URL should be considered and the relevant privacy settings should be evaluated.  In the case of the top-level navigation the document URL should NOT be considered and the connection.  There are no hints that the site owner can provide to indicate what kind of request will be needed so it is up to the browser to guess correctly.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor preconnect requests that are initiated while the document is being loaded (before the onload event while the HTML is being parsed and scripts are being executed), Chrome will assume that preconnect requests are going to be for sub-resources that are going to be requested in the context of the current document and the connection pool will be selected by taking the owning document's URL into account.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor preconnect requests that are initiated after the document has finished loading, Chrome will assume that preconnect requests will be used for future page navigations and the connections will not take the current document's URL into account when selecting a connection pool (which effectively means the connection will be established in the allows-cookies pool).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis does leave a few possible cases for mis-guessing but should handle the vast majority of cases.  Specifically:\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eTop-level navigations that are preconnected before the page has finished loading may end up in the wrong connection pool as the document's URL will be considered.\u003c/li\u003e\u003cli\u003eSub-resource requests that are preconnected after the page has finished loading may end up in the wrong pool if the request requires a private connection.\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2187609824886192973"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/network-stack/preconnect"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3482802397342084043"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4061537406890692522/4"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3482802397342084043"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3482802397342084043"}],"author":[{"name":{"$t":"Patrick Meenan"},"email":{"$t":"pmeenan@chromium.org"}}],"sites$pageName":{"$t":"preconnect"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7527731940178553553"},"published":{"$t":"2015-03-16T17:24:50.184Z"},"updated":{"$t":"2015-03-16T17:30:10.123Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-16T17:30:10.098Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"VideoCaptureBrowserClasses.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7527731940178553553"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5478605515991813275"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/video-capture/VideoCaptureBrowserClasses.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7527731940178553553"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7527731940178553553"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7527731940178553553"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7527731940178553553"}],"author":[{"name":{"$t":"Miguel Casas-Sanchez"},"email":{"$t":"mcasas@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5140583296591473373"},"published":{"$t":"2013-03-28T22:44:52.634Z"},"updated":{"$t":"2015-03-16T17:28:11.947Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-03-28T22:47:06.207Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Video Playback and Compositor"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAuthors: \u003c/span\u003e\u003ca href\u003d\"mailto:jamesr@chromium.org\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ejamesr@chromium.org\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, \u003c/span\u003e\u003ca href\u003d\"mailto:danakj@chromium.org\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edanakj@chromium.org\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe Chromium compositor has support for video playback to support offloading work to the GPU and displaying video frames while the main thread is blocked.  There are a few different media engine implementations in Chromium, but they interact with the compositor in similar ways.  Here’s a diagram of the different classes and how they interact:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cimg height\u003d\"322px;\" src\u003d\"https://lh6.googleusercontent.com/Ubm3huhrrO8rFBTvZxG2h5aAdOJFR9PvyBsBnOr4q0vVzyzGFryquQLsrRf_OWH84E2nd_9ZGF6RPMGUbSXggTdkmg4N9WscPYWiwvLCEhzzEPmVqfqXDKXo\" width\u003d\"616px;\" /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThings in dotted square boxes are interfaces, things in ovals are concrete classes.  Arrows represent pointers between objects.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eObjects by thread (note that a few span multiple threads):\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cimg height\u003d\"342px;\" src\u003d\"https://lh5.googleusercontent.com/AvKsmAQ2zo1X-40GA1d8e9Nb5o5Qn5IGGcytXaDPuYWgS-RY_V9SOzNdbFnZ0jnywb99m821436KnMXo5Z5G8xTMiHMgvebU1qwt7cHa3upPERKUj7ogrqX8\" width\u003d\"625px;\" /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eBefore video playback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) WebMediaPlayerClientImpl constructed by WebCore\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAt start of video load:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) WebMediaPlayerClientImpl constructs WebMediaPlayer\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn SetReadyState, if the video has loaded enough to know we want composited playback:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) WebMediaPlayerImpl constructs a WebLayerImpl wrapping a cc::VideoLayer with the provider pointer set to the WebMediaPlayerImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4.) WebMediaPlayerImpl provides WebLayer* to WebMediaPlayerClientImpl to register in WebCore’s compositing tree\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the next compositor commit during tree sync (on compositor thread with main thread blocked):\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5.) cc::VideoLayer creates a cc::VideoLayerImpl and passes the cc::VideoFrameProvider*\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6.) cc::VideoLayerImpl creates a cc::VideoFrameProviderClientImpl with the provider pointer\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e7.) cc::VideoFrameProviderClientImpl calls SetVideoFrameProviderClient(this) on the cc::VideoFrameProvider*, which is the WebMediaPlayerImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn tree activation (immediately after tree sync when not in impl-side painting, at some point later on in impl-side painting)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e8.) Active tree cc::VideoLayerImpl sets itself as the cc::VideoFrameProviderClientImpl’s active layer\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf we fully initialize without anything shutting down, then the pathway for the video layer to grab a new frame is:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the compositor thread when preparing to draw a frame:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) cc::VideoLayerImpl::WillDraw calls VideoFrameProviderClientImpl::AcquireLockAndCurrentFrame()\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) VFPCI::ALACF takes its provider_lock_ and calls GetCurrentFrame() on its provider\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) WebMediaPlayerImpl takes its internal lock_ and returns its current_frame_\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4.) cc::VideoLayerImpl uploads data into textures (if needed)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the compositor thread when drawing a frame:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5.) cc::VideoLayerImpl::AppendQuads adds quads into the draw list referencing the video texture(s)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the compositor thread after drawing a frame:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6.) cc::VideoLayerImpl::DidDraw calls VideoFrameProviderClientImpl::PutCurrentFrame\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e7.) VFPCI::PCF calls PutCurrentFrame() on its provider\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e8.) cc::VideoLayerImpl::DidDraw calls VFPCI::ReleaseLock which releases provider_lock_\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe way the media system can notify the compositor of new video frames on the compositor thread is (currently implemented only on android):\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the compositor thread when the media system has a new frame available\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) Something in the media playback system (content::StreamTextureProxyImpl for android) calls cc::VideoFrameProvider::DidReceiveFrame()\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) cc::VideoFrameProviderClientImpl checks if it has an active cc::VideoLayerImpl and calls SetNeedsRedraw() on it if so\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) cc::VideoLayerImpl::SetNeedsRedraw tells the compositor to schedule a new frame\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eShutdown\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere are a few ways this system can shut down.  All shutdown paths start on the main thread, but they can propagate out to other threads in different ways depending on the type of shutdown.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eVideo layer removed from compositing tree while playing\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis can happen if a \u0026lt;video\u0026gt; element is detached from the DOM tree or display:none is set on an ancestor of the element.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere are two cases to consider here - impl-side painting off and impl-side painting on.  With impl-side painting off, there is only one cc::VideoLayerImpl associated with a given cc::VideoLayer.  The cc::VideoLayerImpl is always created or destroyed during the tree sync part of commit which happens on the compositor thread with the main thread blocked.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWith impl-side painting on, there are potentially two cc::VideoLayerImpls associated with a given cc::VideoLayer.  One is in the pending/recycle tree and is always created/destroyed during the commit tree sync on the compositor thread with the main thread blocked.  The other is in the active tree and is created/destroyed during tree activation, which happens on the compositor thread while the main thread is \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003enot\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e blocked.  In impl-side painting mode both cc::VideoLayerImpls hold a reference to the same cc::VideoFrameProviderClientImpl.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003ePreconditions\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) WebMediaPlayerClientImpl owns a WebMediaPlayer (which is a WebMediaPlayerImpl)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) WebMediaPlayerImpl owns a WebLayerImpl, which has a ref to a cc::VideoLayer\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) cc::VideoLayer has an associated cc::VideoLayerImpl (two in impl-side painting mode) which reference a cc::VideoFrameProviderClientImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4.) WebMediaPlayerImpl’s provider_client_ pointer points to the cc::VideoFrameProviderClientImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5.) cc::VideoFrameProviderClientImpl’s provider_ pointer points to the WebMediaPlayerImpl\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSequence\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the main thread at any point in time\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) cc::VideoLayer removed from the compositing tree and/or destroyed\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn the next compositor commit on the compositor thread with the main thread blocked:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) Tree sync starts destruction of the cc::VideoLayerImpl (only cc::VideoLayerImpl when not in impl-side painting, pending/recycle layer in impl-side painting)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) ~cc::VideoLayerImpl() calls cc::VideoFrameProviderClientImpl::Stop()\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4.) cc::VFPCI::Stop() calls SetVideoFrameProviderClientImpl(NULL) on its cc::VideoFrameProvider*, which is a WebMediaPlayerImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5.) cc::VFPCI::StopUsingProvider() takes its provider_lock_ and nulls out its provider_\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6.) WebMediaPlayerImpl nulls out its provider_client_ pointer\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e7.) cc::VFPCI::Stop() nulls out its provider_ pointer (again)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf in impl-side painting mode, on tree activation in the compositor thread:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e8.) cc::VideoLayerImpl in active tree destroyed, dropping last reference to cc::VideoFrameProviderClientImpl\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eOrdering\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSteps 2-7 happen on the compositor thread with the main thread blocked.  This means that the compositor cannot be in a frame for any of these steps and nothing on the main thread can advance (i.e. we can’t start shutting down the WebMediaPlayerImpl).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003ePostconditions\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) WebMediaPlayerImpl’s provider_client_ pointer is NULL (as of step 7)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) cc::VideoFrameProviderClientImpl’s provider_ pointer is NULL (as of step 6)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhen impl-side painting is not enabled, then\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) cc::VideoLayerImpl and cc::VideoFrameProviderClientImpl destroyed (as of step 9)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eMedia engine shut down while video layer is in compositing tree\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003ePreconditions\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) WebMediaPlayerClientImpl owns a WebMediaPlayer (which is a WebMediaPlayerImpl)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) WebMediaPlayerImpl owns a WebLayerImpl, which has a ref to a cc::VideoLayer\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) cc::VideoLayer has an associated cc::VideoLayerImpl (two in impl-side painting mode) which reference a cc::VideoFrameProviderClientImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4.) WebMediaPlayerImpl’s provider_client_ pointer points to the cc::VideoFrameProviderClientImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5.) cc::VideoFrameProviderClientImpl’s provider_ pointer points to the WebMediaPlayerImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6.) We’re outside a compositor commit on the main thread\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e7.) The compositor thread may be in any state, including activation or drawing a frame.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSequence\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOn the main thread at any point in time:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) WebMediaPlayerClientImpl destroys its WebMediaPlayer (which is a WebMediaPlayerImpl)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) ~WebMediaPlayerImpl() calls SetVideoFrameProviderClient(NULL) on its provider_client_, which is a cc::VideoFrameProvierClientImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3.) cc::VideoFrameProviderClientImpl::SetVideoFrameProviderClient() takes its provider_lock_\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4.) cc::VideoFrameProviderClientImpl::SetVideoFrameProviderClient() nulls out its provider_ pointer, which pointed to the WebMediaPlayerImpl\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5.) cc:VFPCI::SetVideoFrameProviderClient() releases its provider_lock_\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6.) ~WebMediaPlayerImpl() completes and the object is destroyed\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eOrdering\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) In step (3) the cc::VFPCI takes its provider_lock_.  If the compositor thread is in the middle of drawing a frame (specifically between WillDraw() and DidDraw()), this call will block until the frame is complete\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003ePostconditions\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1.) WebMediaPlayerImpl’s provider_client_ pointer is NULL (as of step 4)\u003c/span\u003e\u003c/p\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2.) cc::VideoFrameProviderClientImpl’s provider_ pointer is NULL (as of step 5)\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/video-playback-and-compositor"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5140583296591473373"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5140583296591473373"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5140583296591473373"}],"author":[{"name":{"$t":"James Robinson"},"email":{"$t":"jamesr@chromium.org"}}],"sites$pageName":{"$t":"video-playback-and-compositor"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7735754422229925248"},"published":{"$t":"2015-03-13T19:46:43.780Z"},"updated":{"$t":"2015-03-13T19:46:43.823Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-13T19:46:43.780Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"BlinkCoordinates.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7735754422229925248"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6453047206629465951"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/blink-coordinate-spaces/BlinkCoordinates.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7735754422229925248"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7735754422229925248"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7735754422229925248"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7735754422229925248"}],"author":[{"name":{"$t":"David Bokan"},"email":{"$t":"bokan@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"XCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9075125316842337239"},"published":{"$t":"2010-09-10T21:35:28.569Z"},"updated":{"$t":"2015-03-13T18:59:37.548Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-13T18:59:36.354Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Verified Boot Data Structures"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Basic-Guidelines\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eBasic Guidelines\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Structures-are-versioned\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eStructures are versioned\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Key-structures-keep-track-of-their-own-key-version-and-algorithm\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eKey structures keep track of their own key version and algorithm\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-The-public-key-and-signature-headers-know-how-to-find-their-data\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eThe public key and signature headers know how to find their data\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Common-structures-are-reused\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eCommon structures are reused\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Major-structures\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eMajor structures\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Key-block\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eKey block\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware-image\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eFirmware image\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Kernel-image\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eKernel image\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Root-of-trust\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eRoot of trust\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Normal-boot\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eNormal boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Recovery-boot\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eRecovery boot\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003eAs the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/platform/vboot_reference/\" target\u003d\"_blank\"\u003everified boot library\u003c/a\u003e has evolved to meet the needs of firmware, kernel boot, and security, we’ve discovered some parts of it can be made easier to work with.  This document describes the refactoring of the verified boot library to address these issues.\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Basic-Guidelines\" /\u003eBasic Guidelines\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Structures-are-versioned\" /\u003eStructures are versioned\u003c/h3\u003eVersioning allows readers to check for older/newer structures. \u003cbr /\u003e\u003cbr /\u003eThis feature lets us add fields to the structures without necessarily breaking old readers and provides an upgrade path for newer readers to handle old structures.  Versioning structures will resolve the issue where kernel and firmware must be updated in unison.\u003cbr /\u003e\u003cbr /\u003eStructures have a major and minor version number.\u003cbr /\u003e\u003cul\u003e\u003cli\u003eReaderMajor !\u003d StructureMajor - fundamental change in struct; do not attempt to parse\u003c/li\u003e\u003cli\u003eReaderMinor \u003d\u003d StructureMinor - all is well\u003c/li\u003e\u003cli\u003eReaderMinor \u0026lt; StructureMinor - reading a newer file; fields have been added to the struct, but the existing reader will be able to ignore them and still function\u003c/li\u003e\u003cli\u003eReaderMinor \u0026gt; StructureMinor - reading an older file; reader won’t find the fields added since version StructureMinor, and should use default values for those fields\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Key-structures-keep-track-of-their-own-key-version-and-algorithm\" /\u003eKey structures keep track of their own key version and algorithm\u003c/h3\u003eWhile public keys generally have some internal structure, it’s not always apparent. We can use various sizes and algorithms for different keys, so we’ve defined a \u003ccode\u003e\u003cb\u003eVbPublicKey\u003c/b\u003e\u003c/code\u003e structure that simply encapsulates the public key data along with its size and algorithm:\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/vbpublickey.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155588711/chromium-os/chromiumos-design-docs/verified-boot-data-structures/vbpublickey.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003ccode\u003e\u003cb\u003eVbSignature\u003c/b\u003e\u003c/code\u003e structures are very similar, but instead of the algorithm and version they only remember the length of data they signed.  A signature data blob is usually a hash that has been encrypted with a private key. The corresponding public key must be used to extract the original hash. In some cases we may also use a VbSignature structure for a nonencrypted hash.\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/vbsignature.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155606105/chromium-os/chromiumos-design-docs/verified-boot-data-structures/vbsignature.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-The-public-key-and-signature-headers-know-how-to-find-their-data\" /\u003eThe public key and signature headers know how to find their data\u003c/h3\u003eGiven a pointer to the \u003ccode\u003eVbPublicKey\u003c/code\u003e or \u003ccode\u003eVbSignature\u003c/code\u003e header, you can find the corresponding data, which may not be immediately following the header itself.  This lets us put the header structs as sub-structs in the major structures (preambles, etc.), followed by the data, without needing to pass in data pointers separately.\u003cbr /\u003e\u003cbr /\u003eFunctions should take header pointers rather than raw data wherever possible.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Common-structures-are-reused\" /\u003eCommon structures are reused\u003c/h3\u003eKeys, signatures, and key blocks are used by firmware and kernel algorithms.  Common code for generating and parsing is reused.\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Major-structures\" /\u003eMajor structures\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Key-block\" /\u003eKey block\u003c/h3\u003eAt the beginning of a firmware or kernel image is a \u003cb\u003ekey block\u003c/b\u003e that contains the subkey used to sign the rest of the data in the image. The subkey itself is signed by some higher key, which is presumably more secure or robust.\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/keyblock.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155628310/chromium-os/chromiumos-design-docs/verified-boot-data-structures/keyblock.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003eThe key block itself is either signed (by Google) or simply checksummed (for self-signed developer images), so only one of the two VbSignatures is used to validate it. The reason we have two VbSignatures in the key block header is so that we can build one image that can be validated in either way, which makes testing and development much simpler.\u003cbr /\u003e\u003cbr /\u003eThis key block structure is identical for firmware and kernel images, so the code to create and verify it can be shared.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Firmware-image\" /\u003eFirmware image\u003c/h3\u003eA firmware image consists of a key block, a firmware \u003cb\u003epreamble\u003c/b\u003e, and the firmware body.  The key block, preamble, and body do not directly point to each other, so they can be read into separate blocks of memory. The firmware preamble is signed by the key block, and contains the signature of the firmware body plus another subkey which will be used to validate the kernel image.\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/firmware.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155649415/chromium-os/chromiumos-design-docs/verified-boot-data-structures/firmware.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Kernel-image\" /\u003eKernel image\u003c/h3\u003eA kernel image consists of a key block, a kernel preamble, and the kernel body.  The key block, preamble, and body do not directly point to each other, so they can be read into separate blocks of memory.\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/kernel.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155667604/chromium-os/chromiumos-design-docs/verified-boot-data-structures/kernel.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Root-of-trust\" /\u003eRoot of trust\u003c/h2\u003eWhen the device is first powered on, it begins execution from a read-only section of flash memory. In addition to (hopefully) secure code, that read-only region contains the primary root keys needed to validate all the rest of the signed images. The structure that locates the root keys and various other read-only components is the GoogleBinaryBlockHeader, or “\u003cb\u003eGBB\u003c/b\u003e”.\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/readonly.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155697374/chromium-os/chromiumos-design-docs/verified-boot-data-structures/readonly.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003eThere are two primary keys in the GBB. The \u003cb\u003eroot key\u003c/b\u003e is used in the normal boot sequence to sign the read/write firmware, which contains subkeys to sign the kernel, and so forth. In recovery mode, only the read-only firmware is executed (because the read/write firmware may have been erased), so the kernel image on the removable drive is signed by the \u003cb\u003erecovery key\u003c/b\u003e.\u003cbr /\u003e\u003cbr /\u003eThere are a total of six separate keypairs involved in the complete boot process (see diagrams below):\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Normal-boot\" /\u003eNormal boot\u003c/h3\u003e\u003col\u003e\u003cli\u003eRead-only firmware looks in the GBB, finds the root key in read-only memory.\u003c/li\u003e\u003cli\u003eThe root key validates the read/write firmware’s keyblock, which contains the\u003cb\u003e firmware data key\u003c/b\u003e.\u003c/li\u003e\u003cli\u003eThe firmware data key validates the firmware preamble (which contains the \u003cb\u003ekernel subkey\u003c/b\u003e) and the read/write firmware body.\u003c/li\u003e\u003cli\u003eThe read/write firmware begins execution.\u003c/li\u003e\u003cli\u003eThe read/write firmware uses the kernel subkey to validate the kernel’s keyblock, which contains the \u003cb\u003ekernel data key\u003c/b\u003e.\u003c/li\u003e\u003cli\u003eThe kernel data key validates the kernel preamble and the kernel blob.\u003c/li\u003e\u003cli\u003eThe kernel begins execution.\u003c/li\u003e\u003cli\u003eThe kernel image contains the hash of hashes, which is used to validate the bundle of hashes used by the block-based rootfs validation scheme.\u003c/li\u003e\u003cli\u003eThe filesystem driver uses the bundle of hashes to validate each block of the rootfs as is read off the disk.\u003c/li\u003e\u003c/ol\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/VerifiedBootDataStructures.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1330555063393/chromium-os/chromiumos-design-docs/verified-boot-data-structures/VerifiedBootDataStructures.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Recovery-boot\" /\u003eRecovery boot\u003c/h3\u003e\u003col\u003e\u003cli\u003eRead-only firmware looks in the GBB, finds the recovery key in read-only memory.\u003c/li\u003e\u003cli\u003eThe recovery key validates the kernel’s keyblock, which contains the \u003cb\u003erecovery kernel data key\u003c/b\u003e. Although it serves the same purpose as the kernel subkey in normal boot, it uses a larger key because the read/write firmware is not used as an intermediate step.\u003c/li\u003e\u003cli\u003eThe recovery kernel data key validates the kernel preamble and the kernel blob.\u003c/li\u003e\u003cli\u003eThe kernel begins execution.\u003c/li\u003e\u003cli\u003eThe kernel image contains the hash of hashes, which is used to validate the bundle of hashes used by the block-based rootfs validation scheme.\u003c/li\u003e\u003cli\u003eThe filesystem driver uses the bundle of hashes to validate each block of the rootfs as it is read from the removable media.\u003c/li\u003e\u003c/ol\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures/recovery.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1284155742228/chromium-os/chromiumos-design-docs/verified-boot-data-structures/recovery.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-data-structures"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9075125316842337239"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9075125316842337239"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9075125316842337239"}],"author":[{"name":{"$t":"Bill Richardson"},"email":{"$t":"wfrichar@chromium.org"}}],"sites$pageName":{"$t":"verified-boot-data-structures"},"sites$revision":{"$t":"15"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8889382987163933669"},"published":{"$t":"2015-03-13T02:06:11.404Z"},"updated":{"$t":"2015-03-13T02:06:11.447Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-13T02:06:11.404Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"menu.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8889382987163933669"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6453047206629465951"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/blink-coordinate-spaces/menu.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8889382987163933669"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8889382987163933669"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8889382987163933669"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8889382987163933669"}],"author":[{"name":{"$t":"David Bokan"},"email":{"$t":"bokan@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2295066818496585921"},"published":{"$t":"2015-03-12T05:11:08.302Z"},"updated":{"$t":"2015-03-12T05:11:08.341Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-12T05:11:08.302Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromium-os-hoho.tar.bz2"},"summary":{},"content":{"type":"application/x-bzip2","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2295066818496585921"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"},{"rel":"alternate","type":"application/x-bzip2","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/hoho/chromium-os-hoho.tar.bz2"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2295066818496585921"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2295066818496585921"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2295066818496585921"},{"rel":"edit-media","type":"application/x-bzip2","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2295066818496585921"}],"author":[{"name":{"$t":"Juan Fantin"},"email":{"$t":"jfantin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2727610315490997660"},"published":{"$t":"2013-09-06T20:14:44.891Z"},"updated":{"$t":"2015-03-12T00:43:03.731Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-09-06T20:22:00.334Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Immersive fullscreen"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003cdiv class\u003d\"sites-layout-name-right-sidebar-hf sites-layout-vbox\"\u003e\u003cdiv class\u003d\"sites-layout-tile sites-tile-name-header sites-layout-empty-tile\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-family:Arial;font-size:15px;white-space:pre-wrap;line-height:1.15\"\u003ejamescook, pkotwicz\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAugust 2013\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eUser Experience\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImmersive fullscreen is a fullscreen mode for the Chrome OS Ash window manager. It allows users with small screens to use almost the entire screen for web content, but still access the tab strip and app shelf when needed.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cimg src\u003d\"https://lh6.googleusercontent.com/4mTHvcSoE3eOhCTWLh3yziRiq67Bfgo0qKZHxC1UXpxRKxQmhT7sJuGhlNeNCnwZvV3ZDk0fI-JoMm4Slp35zJapaYx1vUMktvArbGa760VdXp51DdoFodat\" /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eThe tabs (and location bar) are collapsed into a small strip at the top of the screen. The shelf is similarly collapsed at the bottom of the screen. Showing the strip gives the user a visual target for the mouse.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cimg height\u003d\"120px;\" src\u003d\"https://lh3.googleusercontent.com/saLdLHVhQarR82y2Z9zIK9Qg12aYVX41LxYBUbOs5ro4jTgejhv60Q2Flkt0UNasfy42_CGaMOUcVl8Bc_DA-uMMb1MC3gjd-rZ5He0m4Q0OhdXd8NTShkce\" width\u003d\"500px;\" /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eMousing to the top of the screen slides in the top controls, which are fully interactive.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor a detailed description of the user experience, see Ben’s \u003c/span\u003e\u003ca href\u003d\"https://docs.google.com/a/google.com/document/d/1dequH51rwf8YpU6s5v6htmEozk8VBB5FbtM1jFDOwt4/edit\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003eoriginal proposal\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eTop of screen implementation\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe introduce a TopContainerView that holds the tab strip and location bar. BrowserView continues to hold the page contents and download shelf.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTopContainerView \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003esometimes\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e contains the bookmark bar. If the bookmark bar is visible (“attached” under the location bar) it should slide down over the page. However, on the new tab page the bookmark bar is visually part of the page contents, so the top controls must slide down over it. Therefore the bookmark bar is \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003ereparented\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e between the BrowserView and the TopContainerView as needed.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eInfobars (“Save this password?”) are considered part of the page contents. The TopContainerView always slides over infobars.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThese are the states for the top controls. “Closed” is the steady state.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cimg height\u003d\"258px;\" src\u003d\"https://docs.google.com/a/google.com/drawings/d/s2NLSYoYsxuc8Z5YxLbWGyg/image?w\u003d512\u0026amp;h\u003d258\u0026amp;rev\u003d644\u0026amp;ac\u003d1\" width\u003d\"512px;\" /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDuring the sliding and revealed states the TopContainerView paints to a compositor layer to allow it to be stacked above the web contents layer.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eRevealing the top controls\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe top controls need to feel like they slide open when the user presses the top of the screen, but not trigger accidentally when the user is mousing past web content at the top of the page. A reveal is triggered when the mouse is at the top of screen past a time delay and is moving slowly (or not at all) in a horizontal direction.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn addition to revealing when the user mouses to the top of the screen there are a variety of situations in the UI when the top controls need to be visible. For example:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhen focus is in the location bar (so the user can see what he types)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eMaking a bookmark (the dialog relies on the location bar to show the URL)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOpening the tools menu (so the menu is visually attached to the 3-lines button)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn these situations the top controls need to stay visible even if the mouse moves away from the screen edge. Getting these situations correct was one of the hardest parts of this feature.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003epkotwicz@ introduced a clever ImmersiveRevealedLock class to deal with the visibility issue. Various parts of Chrome code can acquire a lock and hold it until their UI is dismissed. The ImmersiveModeController handles sliding closed the top controls when all locks are destroyed and the mouse is away from the screen edge.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe top controls also stay visible when any child control has focus, which handles the location bar and several other situations. \u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003ePainting the collapsed controls\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe white strips in the collapsed controls (the “light bar”) help reinforce to the user that their tabs are still present. It also provides a place to show loading animations.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe light-bar uses the existing TabStrip for painting, but with a special painting style flag set. This allows the existing tab layout code to be used for the light bar, so the tab positions exactly match. We also recycle most of the loading animation code.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe disadvantaged of this approach is that it requires resizing, relayout and repainting of the tab strip whenever the reveal state changes. However, we decided the benefits of reusing the layout and animation code outweighed this cost.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eBrowser and tab fullscreen\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eChrome supports two internal fullscreen concepts “browser fullscreen” and “tab fullscreen”. Browser fullscreen is entered via UI commands (e.g. Tools menu \u0026gt; Fullscreen). Tab fullscreen is entered when a web page requests fullscreen (e.g. Docs presentations).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImmersive fullscreen is only tied to browser fullscreen. This has two advantages:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1. From the user’s perspective, immersive fullscreen is the only fullscreen state in the Ash window manager. In particular we avoid the confusion Mac OS creates with its two separate “fullscreen” and “presentation mode” commands.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2. Fullscreen videos, presentations and games don’t display the light-bars at the top and bottom of the screen, and the user doesn’t need to do anything special for this to happen.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSee chrome/browser/ui/fullscreen/fullscreen_controller.h for details on the two fullscreen modes.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eTest coverage\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImmersive fullscreen is covered by both unit tests and browser tests. The browser tests are used primarily to verify integration with the rest of the browser’s fullscreen mechanisms. See c/b/ui/views/frame/immersive_mode_controller_ash_unittest.cc and c/b/ui/views/frame/immersive_mode_controller_ash_browsertest.cc.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eAppendix\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDuring the development of immersive fullscreen the instant-extended project (“1993”) experimented with using web content to display the auto-complete suggetsions under the location bar. This presented challenges for layout in immersive fullscreen, as the suggestions were sometimes in a separate web view and sometimes (on the new tab page) part of the primary web content.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe suggestions list has been reverted back to a native UI widget. However, if it becomes web content again this is how the layout code will need to change:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eTab contents position, without 1993:\u003c/span\u003e\u003c/p\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ctable style\u003d\"border:none;border-collapse:collapse;width:624px\"\u003e\u003ccolgroup\u003e\u003ccol width\u003d\"*\" /\u003e\u003ccol width\u003d\"*\" /\u003e\u003ccol width\u003d\"*\" /\u003e\u003c/colgroup\u003e\u003ctbody\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRegular window\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImmersive fullscreen\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBookmark bar hidden\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of omnibox (top_container)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3 pixels from top (omnibox hidden, bookmarks hidden)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBookmark bar attached\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of bookmark bar (top_container)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3 pixels from top (omnibox hidden, bookmarks bar shown during reveals)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNew tab page with bookmark bar detached\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of bookmark bar (not top_container)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebelow bookmarks\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eTab contents position, with 1993:\u003c/span\u003e\u003c/p\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ctable style\u003d\"border:none;border-collapse:collapse;width:624px\"\u003e\u003ccolgroup\u003e\u003ccol width\u003d\"*\" /\u003e\u003ccol width\u003d\"*\" /\u003e\u003ccol width\u003d\"*\" /\u003e\u003c/colgroup\u003e\u003ctbody\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRegular window\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImmersive fullscreen\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNo suggestions\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of omnibox\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3 pixels from top\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSuggestions (in overlay)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of omnibox\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3 pixels from top, overlay contents below top_container\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNTP suggestions (in active)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of omnibox (unless suggestions won’t cover bookmarks, then at top)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ebottom of omnibox (unless suggestions won’t cover bookmarks, then at top)\u003c/span\u003e\u003c/p\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-2 sites-canvas-sidebar sites-layout-empty-tile\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cdiv class\u003d\"sites-layout-tile sites-tile-name-footer sites-layout-empty-tile\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/immersive-fullscreen"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2727610315490997660"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2727610315490997660"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2727610315490997660"}],"author":[{"name":{"$t":"James Cook"},"email":{"$t":"jamescook@chromium.org"}}],"sites$pageName":{"$t":"immersive-fullscreen"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1965992562931653751"},"published":{"$t":"2015-03-10T22:05:37.309Z"},"updated":{"$t":"2015-03-10T22:05:37.360Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-10T22:05:37.309Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2015-03-10 14:52:29.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1965992562931653751"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4431931993782345843"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/submitting-a-performance-bug/Screenshot%20from%202015-03-10%2014:52:29.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1965992562931653751"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1965992562931653751"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1965992562931653751"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1965992562931653751"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8461941043002551507"},"published":{"$t":"2015-03-10T22:05:34.091Z"},"updated":{"$t":"2015-03-10T22:05:34.158Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-10T22:05:34.091Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2015-03-10 14:54:06.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8461941043002551507"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4431931993782345843"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/submitting-a-performance-bug/Screenshot%20from%202015-03-10%2014:54:06.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8461941043002551507"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8461941043002551507"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8461941043002551507"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8461941043002551507"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8307932318346198222"},"published":{"$t":"2015-03-10T22:05:31.366Z"},"updated":{"$t":"2015-03-10T22:05:31.424Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-10T22:05:31.366Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2015-03-10 14:55:28.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8307932318346198222"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4431931993782345843"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/submitting-a-performance-bug/Screenshot%20from%202015-03-10%2014:55:28.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8307932318346198222"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8307932318346198222"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8307932318346198222"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8307932318346198222"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7256334308760221070"},"published":{"$t":"2015-03-10T22:05:12.236Z"},"updated":{"$t":"2015-03-10T22:05:12.285Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-10T22:05:12.236Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2015-03-10 14:52:09.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7256334308760221070"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4431931993782345843"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/submitting-a-performance-bug/Screenshot%20from%202015-03-10%2014:52:09.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7256334308760221070"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7256334308760221070"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7256334308760221070"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7256334308760221070"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Wyl7JmA_\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/727174332690514409"},"published":{"$t":"2009-12-03T06:30:56.131Z"},"updated":{"$t":"2015-03-10T07:04:07.640Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-10T07:04:06.172Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Text Input"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-OBSOLETE:-The-contents-need-to-be-updated\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOBSOLETE: The contents need to be updated\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Abstract\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eAbstract\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Objective\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eObjective\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Background\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eBackground\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Requirements\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eRequirements\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Design\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eDesign\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Basic-architecture\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003eBasic architecture\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Keyboard-layout:-XKB\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003eKeyboard layout: XKB\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Input-method-framework:-IBus\"\u003e\u003cstrong\u003e6.3 \u003c/strong\u003eInput method framework: IBus\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Conversion-engines\"\u003e\u003cstrong\u003e6.4 \u003c/strong\u003eConversion engines\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-User-experience\"\u003e\u003cstrong\u003e6.5 \u003c/strong\u003eUser experience\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Code-location\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eCode location\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-IBus\"\u003e\u003cstrong\u003e7.1 \u003c/strong\u003eIBus\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Configuration-dialog-and-language-selector\"\u003e\u003cstrong\u003e7.2 \u003c/strong\u003eConfiguration dialog and language selector\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Candidate-window\"\u003e\u003cstrong\u003e7.3 \u003c/strong\u003eCandidate window\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-OBSOLETE:-The-contents-need-to-be-updated\" /\u003e\u003cfont color\u003d\"#ff0000\"\u003eOBSOLETE: The contents need to be updated\u003c/font\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Abstract\" /\u003eAbstract\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eChromium OS will be internationalized and will support many languages other than English\u003c/li\u003e\r\n\u003cli\u003eChromium OS will support a variety of text input methods to make text entry as easy as possible for non-English languages\u003c/li\u003e\r\n\u003cli\u003eEnd user language and input-method settings are synchronized with the user's profile in the cloud to enable a consistent user experience from any device\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Objective\" /\u003eObjective\u003c/h2\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eBuild text input support for Chromium OS to make it well internationalized.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Background\" /\u003eBackground\u003c/h2\u003e\r\n\u003cdiv\u003eChromium OS will be supporting multiple languages other than English. Regardless of the UI language (the language shown in menu items and any other strings in Chromium OS), Chromium OS should allow you to type in many languages. We will build text input support for Chromium OS on top of the existing text input technologies available for Linux.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Requirements\" /\u003eRequirements\u003c/h2\u003e\r\n\u003cdiv\u003eChromium OS will provide users several ways to type in text: \u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003eSimple Keyboard:\u003c/b\u003e Users type in characters directly from the keyboard. Examples: English, German\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eSwitchable Keyboard:\u003c/b\u003e Users can switch keyboard mappings (for example, Latin/Cyrillic) and directly type in different character sets based on the current mapping. For example, Russian users can switch the keyboard mapping between Cyrillic and Latin to compose bilingual text.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eSimple IME:\u003c/b\u003e Users type in most characters directly using a simple Input Method Editor (IME) that does some minor tasks such as validation, auto-correction, and composition. Examples: Korean, Thai\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eTransliteration IME:\u003c/b\u003e Users type in English characters that the Transliteration IME directly converts to native characters. Example: Indic\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eCandidate IME:\u003c/b\u003e Users type in all characters indirectly using an IME. For example, Japanese has too many characters to directly map on a keyboard. Using a Japanese IME, users type in the \"sound\" (for example, \"nihon\") to the IME, which provides a set of candidates (for example, \"日本\") that the user selects from.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThere are also Chromium OS-specific requirements, such as supporting both x86 and ARM processors and following Chromium OS UI design guidelines. Meeting all of these requirements is not trivial. We'll reuse existing input technologies as much as possible.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWe will support the following languages by any of the ways listed above.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ctable border\u003d\"0\" bordercolor\u003d\"#888888\" cellspacing\u003d\"0\" style\u003d\"border-style:none;border-collapse:collapse\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:179px;height:174px\"\u003eArabic\u003cbr /\u003e\r\nBulgarian\u003cbr /\u003e\r\nCatalan\u003cbr /\u003e\r\nCroatian\u003cbr /\u003e\r\nCzech\u003cbr /\u003e\r\nDanish\u003cbr /\u003e\r\nDutch\u003cbr /\u003e\r\nEnglish (GB)\u003cbr /\u003e\r\nEnglish (US)\u003cbr /\u003eEstonian\u003cbr /\u003eFilipino\u003cbr /\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"width:137px;height:174px\"\u003eFinnish\u003cbr /\u003eFrench\u003cbr /\u003e\r\nGerman\u003cbr /\u003e\r\nGreek\u003cbr /\u003e\r\nHebrew\u003cbr /\u003e\r\nHindi\u003cbr /\u003e\r\nHungarian\u003cbr /\u003e\r\nIndonesian\u003cbr /\u003e\r\nItalian\u003cbr /\u003e\r\nJapanese\u003cbr /\u003e\r\nKorean\u003c/td\u003e\r\n\u003ctd style\u003d\"width:155px;height:174px\"\u003eLatvian\u003cbr /\u003e\r\nLithuanian \u003cbr /\u003e\r\nNorwegian\u003cbr /\u003e\r\nPolish\u003cbr /\u003e\r\nPortuguese (Brazil)\u003cbr /\u003e\r\nPortuguese (Portugal)\u003cbr /\u003e\r\nRomanian\u003cbr /\u003e\r\nRussian\u003cbr /\u003e\r\nSerbian\u003cbr /\u003eSimplified Chinese\u003cbr /\u003eSlovak\u003c/td\u003e\r\n\u003ctd style\u003d\"width:152px;height:174px\"\u003eSlovenian\u003cbr /\u003e\r\nSpanish\u003cbr /\u003eSpanish in Latin America\u003cbr /\u003e\r\nSwedish\u003cbr /\u003e\r\nThai\u003cbr /\u003e\r\nTraditional Chinese\u003cbr /\u003e\r\nTurkish\u003cbr /\u003e\r\nUkrainian\u003cbr /\u003e\r\nVietnamese\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Design\" /\u003eDesign\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Basic-architecture\" /\u003eBasic architecture\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eFor languages that can be supported by Simple Keyboard or Switchable Keyboard, we'll use \u003ca href\u003d\"http://en.wikipedia.org/wiki/X_keyboard_extension\" rel\u003d\"nofollow\"\u003eXKB\u003c/a\u003e (X Keyboard Extension). For languages in other categories, we'll use \u003ca href\u003d\"http://en.wikipedia.org/wiki/Intelligent_Input_Bus\" rel\u003d\"nofollow\"\u003eIBus\u003c/a\u003e (Intelligent Input Bus). The following diagram illustrates the basic architecture of text input support for Chromium OS.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"border:medium none;margin:0pt 0pt 0pt 40px;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(71,18,100)\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/text-input/basic-architecture2.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1259832806496/chromium-os/chromiumos-design-docs/text-input/basic-architecture2.png\" /\u003e\u003c/a\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Keyboard-layout:-XKB\" /\u003eKeyboard layout: XKB\u003c/h3\u003e\r\n\u003cdiv\u003eWe will create the XKB definition file for each keyboard layout.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Input-method-framework:-IBus\" /\u003eInput method framework: IBus\u003c/h3\u003e\r\n\u003cdiv\u003eWe will use IBus as the input method framework (IM framework). IBus is an open-source input method framework that works as a middle layer between applications and language-specific backend conversion engines.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWe decided to use IBus for the following reasons.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eIt's the default IM framework for Fedora 11 and Ubuntu 9.10.\u003c/li\u003e\r\n\u003cli\u003eNo rebooting is necessary (unlike older IM frameworks) when major configurations are changed, such as when adding a new language.\u003c/li\u003e\r\n\u003cli\u003eApps should be more stable. Unlike older IM frameworks, crashes in conversion engines won't affect applications.\u003c/li\u003e\r\n\u003cli\u003eIBus is implemented on top of D-Bus, which is also used in other components of Chromium OS.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\r\n\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Conversion-engines\" /\u003eConversion engines\u003c/h3\u003e\r\n\u003cdiv\u003eMany conversion engines are available for IBus, such as ibus-pinyin for Chinese. We'll use the following open source conversion engines.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ctable border\u003d\"0\" bordercolor\u003d\"#888888\" cellspacing\u003d\"0\" style\u003d\"border-style:none\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:128px;height:112px\"\u003e \u003cb\u003eIBus engine\u003cbr /\u003e\r\n \u003c/b\u003eibus-pinyin\u003cbr /\u003e\r\n\u003cb\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e ibus-chewing\u003cbr /\u003e\r\n ibus-table\u003cbr /\u003e\r\n ibus-hangul\u003cbr /\u003e\r\n\u003c/span\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"width:300px;height:112px\"\u003e \u003cb\u003eLanguage\u003cbr /\u003e\r\n \u003c/b\u003eChinese (Simplified)\u003cbr /\u003e\r\n Chinese (Traditional - Chewing)\u003cbr /\u003e\r\n Chinese (Traditional - Bopomofo and Cangjie)\u003cbr /\u003e\r\n Korean\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003cfont color\u003d\"#ff0000\"\u003eNew: \u003c/font\u003eFor Japanese, we plan to port \u003ca href\u003d\"http://www.google.com/intl/ja/ime/\"\u003eGoogle Japanese Input\u003c/a\u003e to Chromium OS.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-User-experience\" /\u003eUser experience\u003c/h3\u003e\r\n\u003cdiv\u003eWe'll make the text input experience be uniform with the user experience in Chromium OS. To achieve this goal, we'll rewrite all user interfaces using Chromium's UI toolkit library called Views.\u003c/div\u003e\r\n\u003cdiv\u003e \u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eCandidate window\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWill be implemented as separate process. Communicates to IBus-daemon via D-Bus.\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#FF0000\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#FF0000\"\u003eNew: \u003c/font\u003eHere's a screenshot of a work-in-progress version of the candidate window. \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:483d026d329bff2f\" class\u003d\"disabled\"\u003eA demo\u003c/a\u003e is also available.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/text-input/candidate_window.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1259832991155/chromium-os/chromiumos-design-docs/text-input/candidate_window.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eXKB configuration dialog\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWill be part of Chromium's options dialog. Communicates to X server via libcros.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eIBus configuration dialog\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWill be part of Chromium's options dialog. Communicates to IBus-daemon via libcros.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eConversion engine specific configuration dialogs\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWill be part of Chromium's options dialog. Communicates to conversion engines via libcros.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eInput language selector\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWill be part of Chromium's status area (near the time and the power indicator). Communicates to IBus-daemon and X Server via libcros. We'll integrate the input language selector with the keyboard layout selector, unlike traditional Linux desktops. Here's a mockup of what it will look like:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"border:medium none;margin:0pt 0pt 0pt 40px;padding:0px\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/text-input/input.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1259832806497/chromium-os/chromiumos-design-docs/text-input/input.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eInput language selector (on login manager)\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eProbably not required, because Google accounts (that is, email addresses) used for login are all in ASCII characters, as are the passwords. We will implement it once it becomes necessary. Internationalized keyboards can be supported by XKB configurations.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eSync with the cloud\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eText input-related data is synced with the cloud. We sync the user's choices of languages, keyboard layouts, and input method extensions as described in \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/text-input/syncing-input-methods\"\u003eSyncing Languages and Input Methods\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn the future, we may sync:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eUser settings for XKB, IBus, each IME, and so on.\u003c/li\u003e\r\n\u003cli\u003eUser input history used for better conversions (optional)\u003c/li\u003e\r\n\u003cli\u003eUser-defined dictionaries (optional)\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\r\n\r\n\u003cdiv\u003eSyncing configuration data is a must, but users can opt out of syncing other user data.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eSecurity considerations\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eAn indirect input layer like IBus can be a security weak point, as it can be exploited as a key logger. We plan to use \u003ca href\u003d\"http://en.wikipedia.org/wiki/Grsecurity\" rel\u003d\"nofollow\"\u003eGRSecurity\u003c/a\u003e to restrict resource access from IBus and conversion engines. We also plan to review the security of IBus.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eLong-term goals\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eAlthough the following goals aren't targeted for the initial version, these are some of our long-term goals:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eBetter integration with browsers, such as changing behavior depending on the input form.\u003c/li\u003e\r\n\u003cli\u003eMulti-modal input, such as hand writing and voice recognition.\u003c/li\u003e\r\n\u003cli\u003eVirtual keyboard (aka software keyboard). Web-based virtual keyboard can be used in the initial version, though.\u003c/li\u003e\r\n\u003cli\u003eMulti-keypress input\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Code-location\" /\u003eCode location\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-IBus\" /\u003eIBus\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003echromium-os/src/third_party/ibus/  (Tip of tree of IBus. We'll use the ibus-daemon, ibus-pinyin, ibus-chewing, ibus-table, and ibus-hangul modules as-is. However, we won't use the ibus-setup or ibus-panel modules.) \u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Configuration-dialog-and-language-selector\" /\u003eConfiguration dialog and language selector\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/chromeos/options/\"\u003echromium/src/chrome/browser/chromeos/options\u003c/a\u003e (configuration page)\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://src.chromium.org/cgi-bin/gitweb.cgi?p\u003dcros.git;a\u003dsummary\"\u003echromium-os/src/platform/cros\u003c/a\u003e (libcros part, replacement for ibus-setup and ibus-panel)\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://src.chromium.org/cgi-bin/gitweb.cgi?p\u003dcros.git;a\u003dblob;f\u003dchromeos_ime.cc;hb\u003dHEAD\"\u003echromeos_ime.cc\u003c/a\u003e - APIs used for implementing the candidate window\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://src.chromium.org/cgi-bin/gitweb.cgi?p\u003dcros.git;a\u003dblob;f\u003dchromeos_ime.cc;hb\u003dHEAD\"\u003echromeos_language.cc\u003c/a\u003e - APIs used for manipulating input language status.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Candidate-window\" /\u003eCandidate window\u003c/h3\u003e\u003cdiv\u003e\u003cul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/chromeos/text_input/\"\u003echromium/src/chrome/browser/chromeos/text_input\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/text-input"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/727174332690514409"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/727174332690514409"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/727174332690514409"}],"author":[{"name":{"$t":"Satoru Takabayashi"},"email":{"$t":"satorux@chromium.org"}}],"sites$pageName":{"$t":"text-input"},"sites$revision":{"$t":"32"}},{"gd$etag":"\"Xyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/349937782470366506"},"published":{"$t":"2012-12-14T23:02:44.448Z"},"updated":{"$t":"2015-03-09T23:34:49.683Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-09T23:34:48.151Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Aligned bundling support in LLVM"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eThis document describes the proposal to add aligned instruction bundle support (in short - \"bundling\") in LLVM and its implementation in the MC module.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specification\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eSpecification\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Implementation-in-LLVM-MC\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eImplementation in LLVM MC\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Parsing-and-emitting-sections-and-fragments\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eParsing and emitting sections and fragments\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Laying-out-fragments\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eLaying out fragments\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Writing-fragments-to-the-object-file\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eWriting fragments to the object file\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Performance-impacts\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ePerformance impacts\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Memory-consumption-of-fragment-objects\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eMemory consumption of fragment objects\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Assembler-runtime\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eAssembler runtime\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Emitting-instructions\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eEmitting instructions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Specification\" /\u003eSpecification\u003c/h2\u003e\u003cp\u003eFor the purpose of supporting the Software Fault Isolation (SFI) mechanisms required by Native Client, the following directives are added to the LLVM assembler:\u003c/p\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp\u003e\u003ccode\u003e.bundle_align_mode \u0026lt;num\u0026gt;\u003c/code\u003e\u003c/p\u003e\u003cp\u003e\u003ccode\u003e.bundle_lock \u0026lt;option\u0026gt;\u003c/code\u003e\u003c/p\u003e\u003cp\u003e\u003ccode\u003e.bundle_unlock\u003c/code\u003e\u003c/p\u003e\u003c/div\u003e\u003cp\u003eWith the following semantics:\u003c/p\u003e\u003cp\u003eWhen aligned instruction bundle mode (\"bundling\" in short) is enabled (\u003ccode\u003e.bundle_align_mode\u003c/code\u003e was encountered with an argument \u0026gt; 0, which is the power of 2 to which the bundle size is equal), single instructions and groups of instructions between \u003ccode\u003e.bundle_lock\u003c/code\u003e and \u003ccode\u003e.bundle_unlock\u003c/code\u003e directives cannot cross a bundle boundary.\u003c/p\u003e\u003cp\u003eFurthermore, the \u003ccode\u003e.bundle_lock\u003c/code\u003e directive supports the \u003ccode\u003ealign_to_end \u003c/code\u003eoption, which means that the group has to end at a bundle boundary.\u003cbr /\u003e\u003c/p\u003e\u003cp\u003eFor example, consider the following:\u003c/p\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_align_mode 4\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov1\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov2\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov3\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003cbr style\u003d\"color:rgb(34,34,34)\" /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003eAssuming that each of the \u003ccode\u003emov\u003c/code\u003e instructions is 7 bytes long and \u003ccode\u003emov1\u003c/code\u003e is aligned to a 16-byte boundary, two bytes of NOP padding will be inserted between \u003ccode\u003emov2\u003c/code\u003e and \u003ccode\u003emov3\u003c/code\u003e to make sure that \u003ccode\u003emov3\u003c/code\u003e does not cross a 16-byte bundle boundary.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cbr style\u003d\"color:rgb(34,34,34)\" /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003eA slightly modified example:\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003cbr style\u003d\"color:rgb(34,34,34)\" /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_align_mode 4\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov1\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_lock\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov2\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov3\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_unlock\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cbr style\u003d\"color:rgb(34,34,34)\" /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003eHere, since the bundle-locked sequence \u003ccode\u003emov2 mov3\u003c/code\u003e cannot cross a bundle boundary, 9 bytes of NOP padding will be inserted between \u003ccode\u003emov1\u003c/code\u003e and \u003ccode\u003emov2\u003c/code\u003e.\u003cbr /\u003e\u003cbr /\u003eAn example to demonstrate the \u003ccode\u003ealign_to_end\u003c/code\u003e option:\u003cbr /\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_align_mode 4\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov1\u003c/code\u003e\u003cbr /\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov2\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_lock a\u003c/code\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003elign_to_end\u003c/code\u003e\u003c/font\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov\u003c/code\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e3\u003c/code\u003e\u003c/font\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003emov\u003c/code\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e4\u003c/code\u003e\u003c/font\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e\u003cfont face\u003d\"times new roman, serif\"\u003e\u003ccode\u003e.bundle_unlock\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003eNormally, only two bytes of NOP padding would be required between \u003ccode\u003emov2\u003c/code\u003e and \u003ccode\u003emov3\u003c/code\u003e to ensure that bundle-locked sequence does not cross a bundle boundary. However, since \u003ccode\u003ealign_to_end\u003c/code\u003e was provided, an additional two bytes of NOP padding will be inserted so that the sequence ends at a boundary.\u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cbr style\u003d\"color:rgb(34,34,34)\" /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003eFor information on how this ability is used for software fault isolation by Native Client, see the following resources:\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003ca href\u003d\"http://src.chromium.org/viewvc/native_client/data/site/NaCl_SFI.pdf\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003ehttp://src.chromium.org/viewvc/native_client/data/site/NaCl_SFI.pdf\u003c/a\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003e [PDF link]\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003ca href\u003d\"http://www.chromium.org/nativeclient/reference/arm-overview#TOC-The-Native-Client-Solution:-Bundles-\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003ehttp://www.chromium.org/nativeclient/reference/arm-overview#TOC-The-Native-Client-Solution:-Bundles-\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34)\"\u003eOther papers listed at\u003c/span\u003e\u003cfont style\u003d\"color:rgb(17,85,204)\"\u003e\u003ca href\u003d\"http://www.chromium.org/nativeclient/reference/research-papers\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003e http://www.chromium.org/nativeclient/reference/research-papers\u003c/a\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Implementation-in-LLVM-MC\" /\u003eImplementation in LLVM MC\u003c/h2\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs proposed, bundling is a feature of the assembler. Therefore, it is implemented in the MC module of LLVM. Specifically, the following parts are affected:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eThe assembler parser is modified to parse the new directives and emit appropriate commands to streamers.\u003c/li\u003e\u003cli\u003eThe assembly streamer (used for printing out disassembly) is modified to emit textual directives back from streamer commands.\u003c/li\u003e\u003cli\u003eThe object streamers are modified to act upon the bundling commands to affect the assembly process.\u003c/li\u003e\u003cul\u003e\u003cli\u003eNote: at this point support has only been added to the ELF object streamer. This is done to answer the immediate needs of NaCl and to reduce the complexity of the initial patch. At a later point, bundling support can also be added to the MachO and COFF streamers, if someone is interested.\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eThe main assembler logic is modified to support bundling.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003eThe following description will focus on the path: \u003ci\u003eText assembly -\u0026gt; ELF object streamer -\u0026gt; Assembly -\u0026gt; Object file emission\u003c/i\u003e. This path can be roughly divided to three stages:\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eParse bundling directives and emit a sequence of sections (\u003ccode\u003eMCSectionData\u003c/code\u003e) and fragments (\u003ccode\u003eMCFragment\u003c/code\u003e derivatives) that represent the input. \u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003ePerform layout of the fragments to be valid w.r.t. relaxation and bundling.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eWrite the output object.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Parsing-and-emitting-sections-and-fragments\" /\u003eParsing and emitting sections and fragments\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eIn order to implement bundling, we use the existing assembly parsing facilities in MC, adding support for the new directives. The existing section and fragment abstractions are used, with some flags added to keep the state of the bundling directives encountered. Specifically:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eA \u003ccode\u003eBundleAlignSize\u003c/code\u003e field is added to \u003ccode\u003eMCAssembler\u003c/code\u003e. When the\u003ccode\u003e .bundle_align_mode\u003c/code\u003e directive is parsed, this field is populated with the bundle alignment size (2 to the power of the argument of \u003ccode\u003e.bundle_align_mode\u003c/code\u003e). Setting this field is currently allowed once per assembly file. Subsequent \u003ccode\u003e.bundle_align_mode\u003c/code\u003e directives will be rejected as errors.\u003c/li\u003e\u003cli\u003eThe following state fields are added to MCSectionData and managed by the code parsing \u003ccode\u003e.bundle_lock\u003c/code\u003e and \u003ccode\u003e.bundle_unlock\u003c/code\u003e:\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003ccode\u003eBundleLockState\u003c/code\u003e: keeps track of whether the currently parsed code is in a bundle-locked group (between\u003ccode\u003e .bundle_lock\u003c/code\u003e and\u003ccode\u003e .bundle_unlock\u003c/code\u003e directives) and whether the group has to be aligned to bundle end.\u003cbr /\u003e\u003c/li\u003e\u003cli\u003e\u003ccode\u003eBundleGroupBeforeFirstInst\u003c/code\u003e: keeps track of whether the next instruction parsed will be the first in a bundle-locked group.\u003c/li\u003e\u003cul\u003e\u003cli\u003eTurned on when \u003ccode\u003e.bundle_lock\u003c/code\u003e is encountered\u003c/li\u003e\u003cli\u003eTurned off when an instruction is emitted in the streamer\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003eWhen bundling mode is turned on in the assembler (\u003ccode\u003eBundleAlignSize\u003c/code\u003e \u0026gt; 0), the following rules apply to emitting fragments:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eAll instructions are emitted into separate fragments (either data or instruction fragments, depending on whether they are candidates for relaxation). This is essential because each instruction may potentially need to be padded to obey bundling rules when layout is performed (details below). Bundling does not apply to non-instructions like data, alignment directives, etc.\u003c/li\u003e\u003cli\u003eInstructions in bundle-locked groups get emitted into the same data fragment, since they are all part of the same group which has to be moved and padded together.\u003c/li\u003e\u003cul\u003e\u003cli\u003eTo make this possible, all potentially relaxable instructions inside bundle-locked groups are relaxed before emission, so that they won't need relaxation in the future.\u003c/li\u003e\u003cli\u003eWhile in theory the above means the code can become larger than necessary, in practice instructions actually requiring relaxation won't usually appear in bundle-locked groups, so the practical cost is very low. The gain is a significant simplification of the implementation.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Laying-out-fragments\" /\u003eLaying out fragments\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eBundling blends well into the existing layout mechanism in the MC assembler, since its effects are somewhat similar to relaxation. Some fragments may need to grow due to padding, which may require re-layout of subsequent fragments and recomputation of fixups. Therefore, the MC assembler employs an iterative layout algorithm. The following diagram will help explain the layout of fragments w.r.t. bundling:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/aligned-bundling-support-in-llvm/Fragment%20padding.png.1355408184699.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1355526290127/nativeclient/pnacl/aligned-bundling-support-in-llvm/Fragment%20padding.png.1355408184699.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"text-align:center;margin-right:auto;margin-left:auto\" /\u003e\u003cul\u003e\u003cli\u003eWhen layout on a fragment is performed, the fragment's offset and size are computed.\u003c/li\u003e\u003cli\u003eThe following steps apply only if:\u003c/li\u003e\u003cul\u003e\u003cli\u003eBundling is enabled\u003c/li\u003e\u003cli\u003eThe fragment contains instructions (we don't pad data and alignment fragments)\u003c/li\u003e\u003cul\u003e\u003cli\u003eFor this purpose, a boolean predicate \u003ccode\u003ehasInstructions\u003c/code\u003e is added to \u003ccode\u003eMCFragment\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cli\u003eIf it's determined that the fragment will cross a bundle boundary, padding is required.\u003c/li\u003e\u003cul\u003e\u003cli\u003eThe required amount of padding is computed and stored in the \u003ccode\u003eBundlePudding\u003c/code\u003e field of the fragment.\u003cbr /\u003eThis field is restricted to \u003ccode\u003euint8_t\u003c/code\u003e, in order to save space in the mainstream case (bundling disabled). In practice, fragments of larger size will not be encountered (bundling is done at most on small groups of a few instructions).\u003c/li\u003e\u003cli\u003eThe fragment offset is set to point after the padding, at the start of the actual fragment. This way the following invariant still holds:\u003cbr /\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003ccode\u003efragment offset + fragment size \u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003ccode\u003e\u003d offset of next fragment\u003c/code\u003e \u003cbr /\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003ePadding is also required if the \u003ccode\u003ealign_to_end\u003c/code\u003e option is provided to a bundle-locked group.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eNote\r\n that since we create a single data fragment for a bundle-locked group, \r\nthe above applies to such groups as well as single instructions.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Writing-fragments-to-the-object-file\" /\u003eWriting fragments to the object file\u003c/h3\u003e\u003cdiv\u003e\u003ci\u003eNote: the write target of the assembler is abstracted into a stream object, which can also write into memory. \"Object file\" here implies this stream.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn the last step, the assembler writes the list of fragments into sections according to their layout order. In this step, the \u003ccode\u003eBundlePadding\u003c/code\u003e field created during layout is used to add NOP padding (by calling \u003ccode\u003ewriteNopData\u003c/code\u003e on the target-specific assembler backend) of appropriate size before fragments that require it.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Performance-impacts\" /\u003ePerformance impacts\u003c/h2\u003e\u003cdiv\u003eIt's interesting to study the performance impact of adding the bundling feature on MC's assembler normal operation (without actual bundling directives).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Memory-consumption-of-fragment-objects\" /\u003eMemory consumption of fragment objects\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAmount of bytes needed for the various MCFragment objects on x86-64:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-color:rgb(136,136,136);border-width:1px\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"width:162px;height:30px\"\u003e \u003cb\u003eFragment type\u003c/b\u003e\u003c/td\u003e\u003ctd style\u003d\"width:124px;height:30px\"\u003e\u003cb\u003e Without bundling\u003c/b\u003e\u003c/td\u003e\u003ctd style\u003d\"width:94px;height:30px\"\u003e\u003cb\u003e With bundling\u003c/b\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:162px;height:16px\"\u003e\u003ccode\u003eMCFragment\u003c/code\u003e\u003c/td\u003e\u003ctd style\u003d\"width:124px;height:16px\"\u003e\u003ccode\u003e 64\u003c/code\u003e\u003c/td\u003e\u003ctd style\u003d\"width:94px;height:16px\"\u003e\u003ccode\u003e 64\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:162px;height:15px\"\u003e\u003ccode\u003eMCRelaxableFragment\u003c/code\u003e\u003c/td\u003e\u003ctd style\u003d\"width:124px;height:15px\"\u003e\u003ccode\u003e 320\u003c/code\u003e\u003c/td\u003e\u003ctd style\u003d\"width:94px;height:15px\"\u003e\u003ccode\u003e 320\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:162px;height:15px\"\u003e\u003ccode\u003eMCDataFragment\u003c/code\u003e\u003c/td\u003e\u003ctd style\u003d\"width:124px;height:15px\"\u003e\u003ccode\u003e 240\u003c/code\u003e\u003c/td\u003e\u003ctd style\u003d\"width:94px;height:15px\"\u003e\u003ccode\u003e 240\u003c/code\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eExplanation: the single-byte\u003ccode\u003e BundlePadding\u003c/code\u003e field in \u003ccode\u003eMCEncodedFragment\u003c/code\u003e was placed in space reserved for alignment earlier. The same was done for the boolean \u003ccode\u003eHasInstructions\u003c/code\u003e in \u003ccode\u003eMCDataFragment\u003c/code\u003e.\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Assembler-runtime\" /\u003eAssembler runtime\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003ellvm-mc\u003c/code\u003e was run on a large assembly file (produced by compiling gcc 3.5 into a single assembly file) as follows:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo nice -n -20 perf stat -r 10 llvm-mc -filetype\u003dobj gcc.s -o gcc.o\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThere were no noticeable difference in the runtime of \u003ccode\u003ellvm-mc\u003c/code\u003e with and without the bundling patch.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"4\"\u003eAlternative implementation\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eBundling is similar to relaxation in many aspects which simplifies the implementation. While the performance impact of bundling is negligible as shown, the interaction of these two mechanisms can have a negative effect on memory consumption. When bundling is used, most instructions need to be put in their own fragment. That's because before we have decided the sizes of jumps, we don’t know the relative positions of other instructions, as we might need to insert bundle padding NOPs between them. The only exception are bundle-locked superinstruction sequences which can be stored in a single fragment.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSince there's a memory overhead for storing a fragment, the use of bundling with relaxation significantly increases memory overhead. When translating pexe, pnacl-llc uses \u003ci\u003eK * nexe size\u003c/i\u003e memory. \u003cspan style\u003d\"background-color:transparent\"\u003eThe experimental results show that the value of K is ~17 with the fixed cost of ~50MB. Given that, with the maximum \u003ci\u003epexe\u003c/i\u003e size limited currently to 64MB, \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13.3333330154419px\"\u003epnacl-llc\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e would need over 1.1GB of address space which is significantly more than 768MB that will be available when \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13.3333330154419px;background-color:transparent\"\u003epnacl-llc\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e starts using IRT.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eTherefore, one way to reduce the memory consumption is to disable jump relaxation. In that case, we know that size of all instructions from the beginning and we can write the bundle padding NOPs directly into the fragments while emitting the instructions, thus reducing the number of fragments needed.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Emitting-instructions\" /\u003eEmitting instructions\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eWe have implemented the alternative bundle padding scheme in LLVM MC. Currently, this implementation is only being used when the \u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13.3333330154419px;background-color:transparent\"\u003e-mc-relax-all\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e flag is used. The large bulk of implementation is in the \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13.3333330154419px;background-color:transparent\"\u003eMCELFStreamer::mergeFragment\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e method. We reuse the existing code and emit instructions into their own fragment. We also reuse the existing logic \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003efor calculating bundle boundaries and necessary bundle padding\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e. However, when the jump relaxation is disabled, instead of adding each fragment into the list of fragments held by \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;color:rgb(0,96,0);font-family:monospace;background-color:transparent\"\u003eMCSectionData\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e, we merge it with the current fragment.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/aligned-bundling-support-in-llvm"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/349937782470366506"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/349937782470366506"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/349937782470366506"}],"author":[{}],"sites$pageName":{"$t":"aligned-bundling-support-in-llvm"},"sites$revision":{"$t":"16"}},{"gd$etag":"\"WCl7JmA7\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6874058806991841375"},"published":{"$t":"2010-03-03T23:49:26.310Z"},"updated":{"$t":"2015-03-08T06:31:05.782Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-08T06:31:04.189Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chrome Frame"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Google-Chrome-Frame-was-an-open-source-plug-in-that-seamlessly-brought-Google-Chrome-s-open-web-technologies-and-speedy-JavaScript-engine-to-Internet-Explorer.\" /\u003e\u003cp style\u003d\"margin:0px 0px 1.5em;padding:0px;border:0px;font-weight:normal;font-size:14px;font-family:Roboto,sans-serif;vertical-align:baseline;color:rgb(34,34,34);line-height:22.3999996185303px\"\u003eGoogle Chrome Frame was an open source plug-in that seamlessly brought Google Chrome's open web technologies and speedy JavaScript engine to Internet Explorer.\u003c/p\u003e\u003c/h2\u003e\u003ch2 style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif;font-style:normal;font-variant:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)\"\u003e\u003ca name\u003d\"TOC-If-you-have-Chrome-Frame-installed-please-uninstall-it.-It-is-no-longer-supported-or-updated.You-should-continue-to-encourage-your-users-to-install-and-run-evergreen-browsers-that-is-browsers-that-auto-update-their-users-to-the-latest-and-greatest.-\" /\u003e\u003cul style\u003d\"color:rgb(34,34,34);font-family:inherit;font-size:14px;font-style:inherit;line-height:22.3999996185303px;padding:0px 0px 0px 2em;margin:0px;border:0px;vertical-align:baseline\"\u003e\u003cli style\u003d\"margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eIf you have Chrome Frame installed, please uninstall it. It is no longer supported or updated.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eYou should continue to encourage your users to install and run\u003c/span\u003e \u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e\u003ca href\u003d\"http://tomdale.net/2013/05/evergreen-browsers/\" style\u003d\"color:rgb(66,133,244);outline:none;text-decoration:none;margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\" rel\u003d\"nofollow\"\u003eevergreen browsers\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e, that is, browsers that auto-update their users to the latest and greatest. \u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Google-Chrome-Frame-is-no-longer-supported-and-retired-as-of-February-25-2014.\" /\u003eGoogle Chrome Frame is no longer supported and retired as of February 25, 2014.\u003c/h2\u003e\u003ch2 style\u003d\"font-weight:300;font-family:Roboto,sans-serif;margin:26px 0px 20px;line-height:1.3;font-size:26px;padding:0px;border:0px;vertical-align:baseline;color:rgb(51,51,51);letter-spacing:-0.01em\"\u003e\u003ca name\u003d\"TOC-Please-read-our-June-2013-Chromium-blog-post-for-details.\" /\u003e\u003cspan style\u003d\"font-family:inherit;font-style:inherit;font-weight:inherit;color:rgb(34,34,34);font-size:14px;line-height:22.3999996185303px;background-color:transparent\"\u003ePlease read our June 2013 \u003c/span\u003e\u003ca href\u003d\"http://blog.chromium.org/2013/06/retiring-chrome-frame.html\" style\u003d\"font-family:inherit;font-style:inherit;font-weight:inherit;font-size:14px;line-height:22.3999996185303px;color:rgb(66,133,244);text-decoration:none;margin:0px;padding:0px;border:0px;vertical-align:baseline;background-color:transparent\"\u003eChromium blog post\u003c/a\u003e\u003cspan style\u003d\"font-family:inherit;font-style:inherit;font-weight:inherit;color:rgb(34,34,34);font-size:14px;line-height:22.3999996185303px;background-color:transparent\"\u003e for details.\u003c/span\u003e\u003c/h2\u003e\u003ch3 style\u003d\"font-weight:400;font-family:Roboto,sans-serif;margin:24px 0px 14px;font-size:21px;line-height:1.3;padding:0px;border:0px;vertical-align:baseline;color:rgb(51,51,51)\"\u003e\u003ca name\u003d\"TOC-Chrome-for-Business\" /\u003e\u003cspan style\u003d\"font-family:inherit;font-style:inherit;font-weight:inherit;line-height:1.3;background-color:transparent\"\u003eChrome for Business\u003c/span\u003e\u003c/h3\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Deploying-Chrome-for-Business-lets-you-configure-over-100-policies-to-fit-your-organization-s-needs.-As-an-admin-you-have-solid-control-over-the-browser-deployment-including-managing-updates-supporting-compatibility-of-older-apps-and-installing-extensions-\" /\u003e\u003cspan style\u003d\"font-weight:normal;font-family:inherit;font-style:inherit;color:rgb(34,34,34);font-size:14px;line-height:22.3999996185303px;margin:0px;padding:0px;border:0px;vertical-align:baseline;background-color:transparent\"\u003eDeploying\u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-family:inherit;font-style:inherit;color:rgb(34,34,34);font-size:14px;line-height:22.3999996185303px;background-color:transparent\"\u003e \u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-family:inherit;font-style:inherit;color:rgb(34,34,34);font-size:14px;line-height:22.3999996185303px;margin:0px;padding:0px;border:0px;vertical-align:baseline;background-color:transparent\"\u003e\u003ca href\u003d\"http://www.google.com/chrome/work\" style\u003d\"color:rgb(66,133,244);text-decoration:none;margin:0px;padding:0px;border:0px;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eChrome for Business\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-family:inherit;font-style:inherit;color:rgb(34,34,34);font-size:14px;line-height:22.3999996185303px;margin:0px;padding:0px;border:0px;vertical-align:baseline;background-color:transparent\"\u003e lets you configure over 100 policies to fit your organization's needs. As an admin, you have solid control over the browser deployment, including managing updates, supporting compatibility of older apps, and installing extensions globally.\u003c/span\u003e\u003cdiv /\u003e\u003c/h2\u003e\u003ch3 style\u003d\"font-weight:400;font-family:Roboto,sans-serif;margin:24px 0px 14px;font-size:21px;line-height:1.3;padding:0px;border:0px;vertical-align:baseline;color:rgb(51,51,51)\"\u003e\u003ca name\u003d\"TOC-Chrome-Legacy-Browser-Support\" /\u003e\u003cspan style\u003d\"font-family:inherit;font-style:inherit;font-weight:inherit;line-height:1.3;background-color:transparent\"\u003eChrome Legacy Browser Support\u003c/span\u003e\u003c/h3\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-If-your-organization-wants-to-take-advantage-of-the-Chrome-browser-but-your-users-still-need-to-access-older-websites-and-apps-that-require-Internet-Explorer-you-can-use-Legacy-Browser-Support-to-easily-and-automatically-switch-between-browsers.-When-your-\" /\u003e\u003cp style\u003d\"margin:0px 0px 1.5em;padding:0px;border:0px;font-weight:normal;font-size:14px;font-family:Roboto,sans-serif;vertical-align:baseline;color:rgb(34,34,34);line-height:22.3999996185303px\"\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eIf your organization wants to take advantage of the Chrome browser, but your users still need to access older websites and apps that require Internet Explorer, you can use\u003c/span\u003e \u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e\u003ca href\u003d\"https://www.google.com/intl/en/chrome/business/browser/lbs.html\" style\u003d\"color:rgb(66,133,244);text-decoration:none;margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eLegacy Browser Support\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e \u003c/span\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eto\u003c/span\u003e \u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eeasily\u003c/span\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e and automatically switch between browsers.  When your user clicks a link that requires a legacy browser to open (such as a site that requires ActiveX), the URL will automatically open in the legacy browser from Chrome. You can specify which URLs to launch into a second browser and deploy this Chrome policy for the organization.\u003c/span\u003e \u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eMore info on\u003c/span\u003e \u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003e\u003ca href\u003d\"http://support.google.com/chrome/a/bin/answer.py?hl\u003den\u0026amp;answer\u003d3019558\" style\u003d\"color:rgb(66,133,244);text-decoration:none;margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eLegacy Browser Support in our help center.\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003c/h2\u003e\u003ch3 style\u003d\"font-weight:400;font-family:Roboto,sans-serif;margin:24px 0px 14px;font-size:21px;line-height:1.3;padding:0px;border:0px;vertical-align:baseline;color:rgb(51,51,51)\"\u003e\u003ca name\u003d\"TOC-How-should-I-deliver-feature-forward-experiences-across-browsers-now-\" /\u003e\u003cspan style\u003d\"font-family:inherit;font-style:inherit;font-weight:inherit;line-height:1.3;background-color:transparent\"\u003eHow should I deliver feature-forward experiences across browsers now?\u003c/span\u003e\u003c/h3\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Continue-to-use-feature-detection-to-identify-capabilities-of-a-browser.-Scaling-experiences-across-desktop-and-mobile-in-a-performant-way-may-require-reducing-the-amount-of-effects-for-older-browsers.-You-can-define-a-browser-support-policy-that-outlines-\" /\u003e\u003cp style\u003d\"margin:0px 0px 1.5em;padding:0px;border:0px;font-weight:normal;font-size:14px;font-family:Roboto,sans-serif;vertical-align:baseline;color:rgb(34,34,34);line-height:22.3999996185303px\"\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;font-weight:inherit;font-style:inherit;font-family:inherit;vertical-align:baseline\"\u003eContinue to use feature detection to identify capabilities of a browser. Scaling experiences across desktop and mobile in a performant way may require reducing the amount of effects for older browsers. You can define a browser support policy that outlines the various levels of support and/or consider a low-res edition where the content is very accessible, though it's lacking significant visual and interaction design.\u003c/span\u003e\u003c/p\u003e\u003c/h2\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2433140667124192106"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/chrome-frame-getting-started"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6874058806991841375"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6874058806991841375"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6874058806991841375"}],"author":[{"name":{"$t":"Alex Russell"},"email":{"$t":"slightlyoff@chromium.org"}}],"sites$pageName":{"$t":"chrome-frame-getting-started"},"sites$revision":{"$t":"71"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8741619321732586381"},"published":{"$t":"2015-03-05T13:53:59.441Z"},"updated":{"$t":"2015-03-05T13:53:59.568Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:53:59.441Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"22.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8741619321732586381"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/22.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8741619321732586381"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8741619321732586381"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8741619321732586381"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8741619321732586381"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6745870916782391107"},"published":{"$t":"2015-03-05T13:53:37.057Z"},"updated":{"$t":"2015-03-05T13:53:37.099Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:53:37.057Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"21.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6745870916782391107"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/21.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6745870916782391107"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6745870916782391107"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6745870916782391107"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6745870916782391107"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6891643291296061260"},"published":{"$t":"2015-03-05T13:53:16.450Z"},"updated":{"$t":"2015-03-05T13:53:16.693Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:53:16.450Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"20.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6891643291296061260"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/20.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6891643291296061260"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6891643291296061260"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6891643291296061260"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6891643291296061260"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4623880367710241143"},"published":{"$t":"2015-03-05T13:52:54.520Z"},"updated":{"$t":"2015-03-05T13:52:54.555Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:52:54.520Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"19.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4623880367710241143"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/19.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4623880367710241143"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4623880367710241143"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4623880367710241143"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4623880367710241143"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4670815105310530360"},"published":{"$t":"2015-03-05T13:52:34.240Z"},"updated":{"$t":"2015-03-05T13:52:34.274Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:52:34.240Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"18.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4670815105310530360"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/18.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4670815105310530360"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4670815105310530360"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4670815105310530360"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4670815105310530360"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3705884848873315715"},"published":{"$t":"2015-03-05T13:52:12.779Z"},"updated":{"$t":"2015-03-05T13:52:12.824Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:52:12.779Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"17.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3705884848873315715"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/17.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3705884848873315715"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3705884848873315715"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3705884848873315715"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3705884848873315715"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4442506106927578024"},"published":{"$t":"2015-03-05T13:51:53.875Z"},"updated":{"$t":"2015-03-05T13:51:53.910Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:51:53.875Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"16.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4442506106927578024"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/16.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4442506106927578024"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4442506106927578024"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4442506106927578024"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4442506106927578024"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2523156720015472946"},"published":{"$t":"2015-03-05T13:51:32.328Z"},"updated":{"$t":"2015-03-05T13:51:32.369Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:51:32.328Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"15.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2523156720015472946"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/15.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2523156720015472946"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2523156720015472946"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2523156720015472946"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2523156720015472946"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1246535346635229257"},"published":{"$t":"2015-03-05T13:51:12.094Z"},"updated":{"$t":"2015-03-05T13:51:12.131Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:51:12.094Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"14.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1246535346635229257"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/14.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1246535346635229257"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1246535346635229257"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1246535346635229257"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1246535346635229257"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1638415484093016170"},"published":{"$t":"2015-03-05T13:50:48.674Z"},"updated":{"$t":"2015-03-05T13:50:48.767Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:50:48.674Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"13.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1638415484093016170"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/13.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1638415484093016170"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1638415484093016170"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1638415484093016170"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1638415484093016170"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7291814465577227747"},"published":{"$t":"2015-03-05T13:50:25.902Z"},"updated":{"$t":"2015-03-05T13:50:25.933Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:50:25.902Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"12.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7291814465577227747"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/12.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7291814465577227747"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7291814465577227747"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7291814465577227747"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7291814465577227747"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3163126925942941914"},"published":{"$t":"2015-03-05T13:50:07.670Z"},"updated":{"$t":"2015-03-05T13:50:07.706Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:50:07.670Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"11.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3163126925942941914"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/11.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3163126925942941914"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3163126925942941914"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3163126925942941914"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3163126925942941914"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5187148201674915770"},"published":{"$t":"2015-03-05T13:49:43.708Z"},"updated":{"$t":"2015-03-05T13:49:43.751Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:49:43.708Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"10.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5187148201674915770"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/10.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5187148201674915770"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5187148201674915770"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5187148201674915770"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5187148201674915770"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7893639432331794543"},"published":{"$t":"2015-03-05T13:49:16.332Z"},"updated":{"$t":"2015-03-05T13:49:16.365Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:49:16.332Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"9.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7893639432331794543"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/9.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7893639432331794543"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7893639432331794543"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7893639432331794543"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7893639432331794543"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7947471126628025713"},"published":{"$t":"2015-03-05T13:48:34.125Z"},"updated":{"$t":"2015-03-05T13:48:34.170Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:48:34.125Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"8.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7947471126628025713"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/8.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7947471126628025713"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7947471126628025713"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7947471126628025713"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7947471126628025713"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7571429052386708163"},"published":{"$t":"2015-03-05T13:46:49.616Z"},"updated":{"$t":"2015-03-05T13:46:49.649Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:46:49.616Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"7.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7571429052386708163"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/7.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7571429052386708163"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7571429052386708163"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7571429052386708163"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7571429052386708163"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5599488589710396406"},"published":{"$t":"2015-03-05T13:46:26.626Z"},"updated":{"$t":"2015-03-05T13:46:26.660Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:46:26.626Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"6.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5599488589710396406"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/6.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5599488589710396406"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5599488589710396406"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5599488589710396406"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5599488589710396406"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2701828171155352953"},"published":{"$t":"2015-03-05T13:46:07.221Z"},"updated":{"$t":"2015-03-05T13:46:07.259Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:46:07.221Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"5.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2701828171155352953"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/5.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2701828171155352953"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2701828171155352953"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2701828171155352953"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2701828171155352953"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4677476247094563864"},"published":{"$t":"2015-03-05T13:45:38.452Z"},"updated":{"$t":"2015-03-05T13:45:38.558Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:45:38.452Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"4.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4677476247094563864"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/4.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4677476247094563864"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4677476247094563864"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4677476247094563864"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4677476247094563864"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1840077182168514930"},"published":{"$t":"2015-03-05T13:44:17.376Z"},"updated":{"$t":"2015-03-05T13:44:17.417Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:44:17.376Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"3.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1840077182168514930"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/3.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1840077182168514930"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1840077182168514930"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1840077182168514930"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1840077182168514930"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4237631529591405351"},"published":{"$t":"2015-03-05T13:43:11.774Z"},"updated":{"$t":"2015-03-05T13:43:11.824Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:43:11.774Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"2.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4237631529591405351"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/2.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4237631529591405351"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4237631529591405351"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4237631529591405351"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4237631529591405351"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7626841699337596131"},"published":{"$t":"2015-03-05T13:42:35.608Z"},"updated":{"$t":"2015-03-05T13:42:35.756Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-05T13:42:35.608Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"1.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7626841699337596131"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/1.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7626841699337596131"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7626841699337596131"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7626841699337596131"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7626841699337596131"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4247820765802071693"},"published":{"$t":"2015-03-04T19:32:09.948Z"},"updated":{"$t":"2015-03-04T19:32:09.987Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-04T19:32:09.948Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"speed_logo.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4247820765802071693"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7824456237194375504"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/speed-infra/speed_logo.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4247820765802071693"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4247820765802071693"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4247820765802071693"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4247820765802071693"}],"author":[{"name":{"$t":"Annie Sullivan"},"email":{"$t":"sullivan@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4616170668190760297"},"published":{"$t":"2015-03-03T15:42:48.199Z"},"updated":{"$t":"2015-03-03T17:01:35.626Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-03-03T17:01:35.626Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Ice Cream Sandwich Support Deprecation"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-What-is-happening-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhat is happening?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eChrome 42 will be the last supported release of Chrome for Android on all Ice Cream Sandwich (Android 4.0) devices.  Ice Cream Sandwich (ICS) users will receive no further updates to Chrome on Android.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Why-the-change-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhy the change?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhile the number of Ice Cream Sandwich devices is shrinking, supporting them in terms of engineering effort and technical complexity is increasingly difficult over time. Each new feature or web capability that’s added to Chrome must be built and tested for ICS. Often workarounds and special cases have to be added specifically for ICS, and that adds code complexity, slows performance, and increases development time.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe number of ICS devices is now sufficiently small that we can better serve our users by phasing out support for earlier devices and focusing on making Chrome better for the vast majority of users on more modern devices. \u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-What-does-this-mean-for-users-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhat does this mean for users?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eUsers on Ice Cream Sandwich can continue to use Chrome, but will not receive updates beyond Chrome 42.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-How-many-devices-will-be-affected-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow many devices will be affected?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIce Cream Sandwich makes up a small percentage of devices with a recent version of Chrome for Android. Over the past year we’ve seen a thirty percent decrease in the overall number of users using Chrome on Ice Cream Sandwich.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-When-is-the-last-Chrome-release-for-Ice-Cream-Sandwich-devices-scheduled-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhen is the last Chrome release for Ice Cream Sandwich devices scheduled?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eChrome 42 will be the last update on Ice Cream Sandwich, and is expected to be released in mid-April 2015. Chrome 43 will no longer support ICS and is expected to be released toward the end of May 2015.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Will-there-be-any-further-Chrome-updates-or-security-patches-for-ICS-devices-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWill there be any further Chrome updates or security patches for ICS devices?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe will continue to issue patches while Chrome 42 is the most recent Chrome version. Once Chrome 43 is released, we don’t plan to issue further updates for ICS devices.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-What-will-happen-to-the-code-supporting-ICS-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhat will happen to the code supporting ICS?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe will be removing the code for ICS from trunk after the branch point for Chrome 43.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Are-there-other-Android-versions-affected-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAre there other Android versions affected?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNo. This only affects Ice Cream Sandwich.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-How-can-I-handle-developing-for-two-versions-of-Chrome-What-should-I-tell-my-users-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow can I handle developing for two versions of Chrome? What should I tell my users?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe encourage all developers irrespective of browser platform to consider progressive enhancement when it comes to building apps and sites.  By using progressive enhancement you will be able to offer a good experience for as many users as possible and in the case of the platform’s capabilities you will be able to detect which features you will be able to support and which you might need to polyfill.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Where-can-I-ask-more-questions-or-leave-feedback-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhere can I ask more questions or leave feedback?\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.38;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor end users, Chrome has an extensive feedback reporting tool (accessible from the Chrome menu).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor developers, the \u003c/span\u003e\u003ca href\u003d\"https://groups.google.com/a/chromium.org/forum/#!forum/chromium-discuss\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003echromium-discuss\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e mailing list is a good place to start if you have specific issues with Ice Cream Sandwich (note it is not a general support channel), or reach out to @\u003c/span\u003e\u003ca href\u003d\"https://twitter.com/ChromiumDev\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eChromiumDev\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e on Twitter.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4852676552341181359"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/ice-cream-sandwich-support-deprecation-faq"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4616170668190760297"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4616170668190760297"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4616170668190760297"}],"author":[{"name":{"$t":"Paul Kinlan"},"email":{"$t":"paulkinlan@chromium.org"}}],"sites$pageName":{"$t":"ice-cream-sandwich-support-deprecation-faq"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7514342208038025137"},"published":{"$t":"2008-09-04T23:17:58.876Z"},"updated":{"$t":"2015-02-25T01:13:15.645Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-25T01:13:12.770Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Memory Usage Backgrounder"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"font-size:18px;font-weight:bold\"\u003eChromium Memory Usage\u003cbr /\u003e\r\n\u003c/span\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eHere is some background information if you are measuring memory in Chromium.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eMulti-Process Model Background\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eTo understand Chromium's memory usage, let's understand the multi-process model.  Unlike other browsers, Chromium is divided into multiple processes. When Chromium starts up, it will initially have two processes.  One process is the \u003cb\u003ebrowser process\u003c/b\u003e which controls the main browser functionality, and the other is the initial \u003cb\u003erenderer process\u003c/b\u003e, which runs the Blink rendering engine and JavaScript (V8).  Each time you open a new tab in Chromium, you'll likely get a new renderer process.  With typical browsing, it is common to see 5-7 chrome.exe processes active.  Further, if you utilize plugins, apps, or extensions, they may also execute within independent processes.  All of Chromium's processes, whether it is a browser process, a renderer process, or a plugin process, will show under the Task Manager as \"chrome.exe\".\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eHere is a screenshot of what you might see from Windows 8 running Chromium:\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder/taskmanager.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Windows task manager displaying multiple Chrome processes.\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1424826327518/developers/memory-usage-backgrounder/taskmanager.jpg\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eIf you were to look at the above table on Windows XP, the numbers for Memory would be significantly larger.  This is because Windows Vista and higher has updated the primary metric for measuring process memory since Windows XP.  Both operating systems primarily measure a process' \u003cb\u003eworking set\u003c/b\u003e - that is the number of bytes held in physical memory on behalf of that process. However, the working set is made up of three distinct components:\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003ePrivate Working Set\u003c/b\u003e\u003cbr /\u003e\r\nResident pages which are private only to this process\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eShareable Working Set\u003c/b\u003e\u003cbr /\u003e\r\nResident pages which may be shared with other processes.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eShared Working Set\u003c/b\u003e\u003cbr /\u003e\r\nResident pages which are currently being shared with other processes.  This is a subset of the Shareable Working Set.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eIn Windows XP, each process is measured by its total working set.  In Windows Vista the definition was changed to just be the private working set.  This actually makes more sense, because the total working set will change based on what other processes are currently running. Thus, if you want to measure a reproducible metric for memory, the Private Working Set is generally a better measure.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eHow to Measure Memory\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eIt turns out that there are several ways to look at memory.  For Chromium, we really wanted to find a measure which is a true reflection of the actual system resources used by the application. We couldn't use the Total Working Set, because this measure double-counts the shared memory used by each process.  Almost all windows applications benefit from at least some amount of shared memory, and Chromium is no exception.  For example, each process typically loads several Windows DLLs (such as kernel32, ntdll, user32, and more), and these DLLs are shared by Windows across all running processes; double counting this memory within Chromium would make it appear to be 10-50MB larger than it really is.  \u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe primary metric we selected for Chromium is a measurement which is similar to what Windows uses.  We measure the working set.  However, unlike Windows Task Manager, we consider which memory is shared and which is not.  We also wanted to make sure that if Chromium loads DLLs which no other process uses, that those are counted as memory used specifically by Chromium. The final algorithm for \"Private\" size is:  Private Working Set + Shareable Working Set - Shared Working Set.  This is close to Window XP's measurement of memory, except for that it also accounts for shared memory.  \u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe simplest way to look at total memory used by Chromium is to use the \u003cb\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eChromium \u003c/span\u003eabout:memory \u003c/b\u003efeature. Simply type 'about:memory' into Chromium's URL bar, and you might see something like this:\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder/aboutmemory.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Chrome\u0026amp;#39;s about:memory page, displaying the breakdown of memory among tabs and other processes.\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1424826391417/developers/memory-usage-backgrounder/aboutmemory.jpg\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAt the top of the page is a summary of the overall memory usage.  If you just want a single number for Chromium's memory usage, the Private column is the best figure which aggregates all memory used by all Chromium processes.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe rest of the numbers on the page provide more detailed breakdowns about memory usage within Chromium.  The Summary section provides aggregate information across processes used by the browser, and the Processes section enumerates the memory usage used by each active chrome.exe process.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eWhen the about:memory page is loaded, Chromium also looks for other browsers (Firefox, Opera, Safari, or IE) that are running and includes them within the summary for a quick comparison.  We use the same metric for measuring each browser (including IE8's multi-process mode).\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eHow to Measure Memory Part 2\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eLooking at an application's Working Set is not the only way to measure memory.  While it does provide a good general measure, what about other system resources consumed which may not show up as part of a process' working set?  As it turns out, there are system resources allocated by any application.  A common resource consumed is GDI memory; this memory will show up in the system's commit charge and may not be reflected in the working set. \u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eTo measure this, we need to look at the system's \u003cb\u003eTotal Commit Charge\u003c/b\u003e.  The total commit charge measures the total amount of memory used by all applications and the system itself. Because this measurement is a system-wide measurement rather than a per-process measurement, it is much trickier to measure.  It is also sensitive to any background processes or services which may run unbeknownst to the user while executing the test.  However, the basic procedure is this:\u003cbr /\u003e\r\n\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eshut down any unnecessary services\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003ereboot\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003emeasure the Total Commit Charge of the system (1)\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003erun the application test (chrome.exe)\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003emeasure the Total Commit Charge of the system (2)\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eclose the application\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003emeasure the Total Commit Charge of the system (3)\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eTo verify that the test was valid, measurements (3) and (1) should be almost identical.  The \"Total Commit Charge\" will be the difference between measurement (2) and (1). \u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eWe've executed these tests for Chromium, and it scores reasonably well.  These tests are complicated, and results vary greatly depending on the operating system version, video drivers installed, and hardware configuration. \u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eWeaknesses of a Multi-Process Model on Memory Usage\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eUsing a multi-process model within the browser offers benefits for reliability, robustness, and security of the browser.  Those benefits drove our design toward the multi-process model, and you can read more about them \u003ca href\u003d\"https://sites.google.com/a/google.com/the-chrome-project/developers/design-documents/process-models\" title\u003d\"here\" rel\u003d\"nofollow\"\u003ehere\u003c/a\u003e.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eHowever, using multiple processes is somewhat at odds with building a lightweight browser. First off, each process does have some amount of overhead.  The process overhead turns out to be relatively small, however, once you've accounted for the shared memory properly.  The more significant handicaps are the replicated internal components of a browser, such as caches, JavaScript VM heaps, and internal data structures which must be duplicated inside multiple processes.  JavaScript is particularly troublesome because of its garbage collected heap.  Heaps are generally relatively large and must be replicated across each browser process.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eHow can Chromium overcome these deficiencies?  In short, it can't :-)  All we can do is to make everything else that much smaller, so that the effects of being multi-process is minimized.  As a result, there are degenerate cases where Chromium uses a lot more RAM than other browsers. The case which is worst is where many tabs are open, each to separate domains with large amounts of JavaScript. But for typical usage, we think Chromium fares well at balancing the benefits of multiple processes and also maintaining memory usage at levels which is lower than some popular browsers.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eNote to techies:  Check out single process mode.  To see how Chromium would fare if it were not a multi-process model, you can ditch the multi-process model and run Chromium in 'single process mode' (use the --single-process command line option). \u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cb\u003eBenefits of a Multi-Process Model on Memory Usage\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eDespite the obvious negative impact of multiple processes on memory usage, it turns out there are some unique benefits which in the long run may dramatically overshadow the downsides. These are benefits which are simply not available to single-process model browsers.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eThe first benefit is that the multi-process browser more readily reclaims unused memory than single-process models.  Here is a quick test to run at home.   Run a Chromium browser, and also a single-process browser side by side.  Open up several tabs - say 10 tabs to different sites. Use each browser a bit. Then, close 9 of the tabs and look at the memory usage of the browser. What you'll notice is that while Chromium is able to give back almost all of the memory used for those tabs, the single-process browsers cannot.  Those same data structures, caches, and Javascript heaps which must be replicated in the multi-process model cannot be purged in the single-process model!  This has a dramatic impact on your browsing experience over time. With Chromium, when you close a tab, it's resources are completely flushed.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eAnother benefit of the multi-process model is that Chromium can actively help the operating system when memory is tight.  Windows already has a feature where when a foreground application is minimized it will tell Windows that the application's memory can be reclaimed if necessary.  As long as there is plenty of RAM, this has no effect on system performance. However, when RAM is tight, the OS knows to take pages from the minimized application rather than the applications which the user may still be using.  Similarly, Chromium employs this exact same model for active tabs.  It is quite common for some users to have 12-15 tabs open concurrently, but only 2-3 of those tabs to be actively in use.  Some of those tabs may not have been touched for days!  As you use Chromium, it will actively tell Windows that the tabs which are not in use should be paged out first.  Single-process browsers cannot differentiate which memory is in use by which tabs.\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eFinally, a third benefit to the multi-process browser's memory usage is the ability to selectively cleanup unused memory.  Below is a screenshot of Chromium's  Task Manager.  To activate the Task Manager, click the menu button in the upper right -\u0026gt; More tools -\u0026gt; Task Manager (or just press Shift-Esc).  A screenshot is included below:\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder/chrometaskmanager.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Chrome\u0026amp;#39;s task manager showing the CPU and memory usage of its tabs and processes.\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1424826700651/developers/memory-usage-backgrounder/chrometaskmanager.jpg\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eIn the unfortunate event that your browser is using more memory than you'd like it to, you can use Chromium's Task Manager to get a glimpse at which tabs are using the most memory.  If you spot an errant plugin process or tab using more than you want, you can kill it using the \"End process\" button, and instantly reclaim that memory.  Your browser will keep running.  Without the help of multiple processes, this would not be possible.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-weight:bold\"\u003eHelping the Operating System\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:normal\"\u003eWindows today uses several hints to help the operating system manage memory.  One of these is reducing the working set when a process is not in use.  For example, if you minimize a windows application, Windows will automatically release the working set of that application to the OS.  If there is plenty of RAM, this has little effect; however, when memory is tight, the OS uses this information to decide which pages to page out first.  (You can test this yourself - run Outlook, and check its memory usage.  Then minimize it.  Watch the working set shrink to a very small size).  \u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eJust as Windows can do this for desktop applications, a multi-process browser can do this for tabs.  When you navigate away from a tab, Chrome uses this as a hint that the resource for that tab are less important than your foreground tab.  Chrome will lower the priority of the now backgrounded tab and also give back a portion of the working set for that tab to the OS. \u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eGiving back pages to the OS when there are no RAM constraints is somewhat of a no-op; but when other applications need the memory, Chrome is \"nice\" and yields its memory so that foreground applications (Chrome or any other app) can be responsive.  Users on low memory machines definitely notice the difference.  Imagine having 15 tabs open, but only being \"active\" in 2 of them.  You'd rather have those two be snappy than have all 15 compete for RAM.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eLikewise, if you leave Chrome idle for periods of time, it will attempt to give back RAM to the operating system.  You aren't using it, so giving it back helps other applications.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-weight:bold\"\u003ePartial TODO List For Reducing Memory Usage\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eHere is a partial list of things we can do to improve memory usage.  Most of these apply to Blink and Chromium; if possible, please try to fix within the Blink project for maximal re-use of code.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eFont management:  The way fonts are cached in memory is fairly sparse.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eStrings:  Duplicate strings are bad.  All strings in Blink/Chromium are unicode strings, even if the string could be encoded with a single-byte encoding.  This has been measured to add up to megabytes of extra space.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eHistory subsystem:  The SQLite DB for history could be optimized.  This will particularly help keep Chromium lean with usage-over-time.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eIn Memory Cache:  Chrome currently uses a shared memory cache across all processes.  Maximum size is currently 32MB, partitioned across the active processes.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eJavascript:  Since Chrome renderers each generally have their own JavaScript VM, reducing memory usage in Javascript pays benefits repeatedly.  See the V8 project for more information.\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:left;padding-top:1em;padding-bottom:1em;padding-right:0px;padding-left:0px;margin-top:0px;margin-bottom:0px\"\u003eTools:  Better real-time tools is always needed.  The memory_watcher project is currently used for debugging.\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7514342208038025137"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7514342208038025137"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7514342208038025137"}],"author":[{}],"sites$pageName":{"$t":"memory-usage-backgrounder"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8424801366314760382"},"published":{"$t":"2015-02-25T01:11:40.607Z"},"updated":{"$t":"2015-02-25T01:11:40.651Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-25T01:11:40.607Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chrometaskmanager.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8424801366314760382"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7514342208038025137"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder/chrometaskmanager.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8424801366314760382"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8424801366314760382"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8424801366314760382"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8424801366314760382"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3310237095841392815"},"published":{"$t":"2015-02-25T01:06:31.387Z"},"updated":{"$t":"2015-02-25T01:06:31.417Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-25T01:06:31.387Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"aboutmemory.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3310237095841392815"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7514342208038025137"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder/aboutmemory.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3310237095841392815"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3310237095841392815"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3310237095841392815"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3310237095841392815"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3495324594414277952"},"published":{"$t":"2015-02-25T01:05:27.480Z"},"updated":{"$t":"2015-02-25T01:05:27.518Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-25T01:05:27.480Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"taskmanager.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3495324594414277952"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7514342208038025137"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/memory-usage-backgrounder/taskmanager.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3495324594414277952"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3495324594414277952"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3495324594414277952"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3495324594414277952"}],"author":[{"name":{"$t":"Ryan Schoen"},"email":{"$t":"rschoen@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6200740244834359521"},"published":{"$t":"2015-02-20T21:49:01.274Z"},"updated":{"$t":"2015-02-20T21:49:01.307Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-20T21:49:01.274Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"gpuraster.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6200740244834359521"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3816860417126212169"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/chromium-graphics/how-to-get-gpu-rasterization/gpuraster.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6200740244834359521"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6200740244834359521"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6200740244834359521"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6200740244834359521"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3876207536981759324"},"published":{"$t":"2015-02-10T19:21:45.487Z"},"updated":{"$t":"2015-02-10T19:21:45.519Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-10T19:21:45.487Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"WebPageReplayDiagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3876207536981759324"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7838125666817701071"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/telemetry/record_a_page_set/WebPageReplayDiagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3876207536981759324"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3876207536981759324"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3876207536981759324"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3876207536981759324"}],"author":[{"name":{"$t":"Ethan Kuefner"},"email":{"$t":"eakuefner@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2435544497898283864"},"published":{"$t":"2015-02-06T00:30:43.781Z"},"updated":{"$t":"2015-02-06T00:30:43.815Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-06T00:30:43.781Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Chrome Media Router Architecture (1).png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2435544497898283864"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/Chrome%20Media%20Router%20Architecture%20(1).png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2435544497898283864"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2435544497898283864"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2435544497898283864"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2435544497898283864"}],"author":[{"name":{"$t":"Mark Foltz"},"email":{"$t":"mfoltz@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2916329567581236565"},"published":{"$t":"2015-02-06T00:29:05.058Z"},"updated":{"$t":"2015-02-06T00:29:05.086Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-06T00:29:05.058Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Chrome Media Router Architecture.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2916329567581236565"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/Chrome%20Media%20Router%20Architecture.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2916329567581236565"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2916329567581236565"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2916329567581236565"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2916329567581236565"}],"author":[{"name":{"$t":"Mark Foltz"},"email":{"$t":"mfoltz@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1903381366262534789"},"published":{"$t":"2014-07-23T16:57:52.069Z"},"updated":{"$t":"2015-02-05T16:53:00.709Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-23T16:58:48.892Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"graphicsdebugger.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1903381366262534789"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4737016800452485121"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/debugging-on-windows/graphics-debugging-in-visual-studio-2013/graphicsdebugger.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1903381366262534789"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1903381366262534789"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1903381366262534789"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1903381366262534789"}],"author":[{"name":{"$t":"Hendrik Wagenaar"},"email":{"$t":"hendrikw@chromium.org"}}],"sites$revision":{"$t":"3"}},{"gd$etag":"\"XSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4737016800452485121"},"published":{"$t":"2014-07-22T23:04:27.076Z"},"updated":{"$t":"2015-02-05T16:53:00.708Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-02T17:29:22.199Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Graphics Debugging in Visual Studio 2013"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eVisual Studio 2013 has a built-in graphics debugger that can capture a rendered frame.  This is a replacement for PIX.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eTo use it with Chromium:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ePass the command arguments:\u003cfont face\u003d\"courier new, monospace\"\u003e \u003c/font\u003e\u003c/span\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e--no-sandbox --in-process-gpu\u003c/font\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eTo enable gpu rasterization, include the command line arguments: \u003cfont face\u003d\"courier new, monospace\"\u003e--force-gpu-rasterization --enable-impl-side-painting\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003eYou might need following hack or something\u003c/li\u003e\u003c/ul\u003e\r\n\u003cpre\u003ediff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc\r\nindex 05e45bd..46db961 100644\r\n--- a/content/app/content_main_runner.cc\r\n+++ b/content/app/content_main_runner.cc\r\n@@ -401,6 +401,11 @@ int RunNamedProcessTypeMain(\r\n { switches::kGpuProcess, GpuMain },\r\n #endif // !CHROME_MULTIPLE_DLL_BROWSER\r\n };\r\n+ base::CommandLine\u0026amp; command_line \u003d\r\n+ *base::CommandLine::ForCurrentProcess();\r\n+ command_line.AppendSwitch(switches::kInProcessGPU);\r\n+ command_line.AppendSwitch(switches::kNoSandbox);\r\n\u003c/pre\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eWithin Visual Studio, show the Graphics toolbar\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eClick File\u0026gt;Open\u0026gt;Project/Solution, and then click your chrome.exe FYI, release build chrome.exe/content_shell.exe works well.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eClick the \"Start Diagnostics\" button on the Graphics toolbar\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eWhile hardware accelerated graphics are being rendered within Chromium, press the Print Scrn key, or the \"Capture Next Rendered Frame\" button on the Graphics toolbar\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eEach frame time will be super imposed on top of Chrome.  If you don't see this then the Graphics Debugger is not working correctly and you won't be able to capture frames.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/how-tos/debugging-on-windows/graphics-debugging-in-visual-studio-2013/graphicsdebugger.png?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1423155180709/developers/how-tos/debugging-on-windows/graphics-debugging-in-visual-studio-2013/graphicsdebugger.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eHere is a description of some of the more important elements of the Graphic Debugger (numbers correspond to the highlighted part on the above image):\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003eThe Graphic toolbar\u003c/li\u003e\r\n\u003cli\u003eThe \u003ci\u003eGraphic Event List\u003c/i\u003e pane keeps a complete history of the calls to create the frame.  Clicking through the list will generate a preview of the frame up to the call that you have selected in the .vsglog frame in the center.\u003c/li\u003e\r\n\u003cli\u003eWithin the event list, you can find objects that were created by or used in a function call\u003c/li\u003e\r\n\u003cli\u003eThe \u003ci\u003eGraphics Object Table \u003c/i\u003econtains a list of all objects used during the frame\u003c/li\u003e\r\n\u003cli\u003eThe name of an object is set within the chrome source.  For example, if you search for \"\u003cfont face\u003d\"courier new, monospace\"\u003eOffscreen back buffer texture\u003c/font\u003e\", you will find it in the function \u003cfont face\u003d\"courier new, monospace\"\u003e\"\u003cfont color\u003d\"#6fa8dc\"\u003eSwapChain11\u003c/font\u003e::resetOffscreenTexture\"\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003eSome calls within the \u003ci\u003eGraphics Event List \u003c/i\u003ewill give you a call stack (usually, you must click directly on a DirectX function to get a call stack)\u003c/li\u003e\r\n\u003cli\u003eIf you double click an object in the \u003ci\u003eGraphics Object Table\u003c/i\u003e, you can get details on the object.  If it is a texture, it will open and display the texture\u003c/li\u003e\r\n\u003cli\u003eIf you double click on a shader in the \u003ci\u003eGraphics Object Table\u003c/i\u003e, you can open a temporary file that shows the shader code\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cdiv\u003eYou can find more information on the Graphics Debugger at \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"http://msdn.microsoft.com/en-us/library/hh873207.aspx\" rel\u003d\"nofollow\"\u003ehttp://msdn.microsoft.com/en-us/library/hh873207.aspx\u003c/a\u003e and \u003c/span\u003e\u003ca href\u003d\"https://www.youtube.com/watch?v\u003dj4SpasLF6Co\" style\u003d\"font-family:Arial,sans-serif;font-size:12px;line-height:18.2000007629395px;background-color:rgb(255,251,225)\" target\u003d\"_blank\"\u003ehttps://www.youtube.com/watch?v\u003dj4SpasLF6Co\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eYou may find it useful to use the configuration manager within Visual Studio to create multiple debug targets. For example, you can set up a second configuration to pass the gpu specific flags\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5941679169189588859"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/debugging-on-windows/graphics-debugging-in-visual-studio-2013"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4737016800452485121"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4737016800452485121"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4737016800452485121"}],"author":[{"name":{"$t":"Hendrik Wagenaar"},"email":{"$t":"hendrikw@chromium.org"}}],"sites$pageName":{"$t":"graphics-debugging-in-visual-studio-2013"},"sites$revision":{"$t":"14"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8876156596757877203"},"published":{"$t":"2010-09-23T20:23:27.739Z"},"updated":{"$t":"2015-02-05T16:53:00.708Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-09-23T20:23:27.739Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"StepIntoSpecific.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8876156596757877203"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5941679169189588859"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/debugging-on-windows/StepIntoSpecific.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8876156596757877203"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8876156596757877203"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8876156596757877203"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8876156596757877203"}],"author":[{"name":{"$t":"Vincent Scheib"},"email":{"$t":"scheib@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2892488896540213532"},"published":{"$t":"2015-02-04T02:57:09.855Z"},"updated":{"$t":"2015-02-04T02:57:09.855Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-04T02:57:09.855Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7582987878577786924"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2892488896540213532"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2892488896540213532"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2892488896540213532"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Brand \u0026 Model Number","$t":"HP Compaq 6820s"},{"index":"B","name":"Wifi","$t":"No"},{"index":"C","name":"Ethernet","$t":"on"},{"index":"D","name":"Trackpad","$t":"on"},{"index":"E","name":"Suspend/Resume","$t":""},{"index":"F","name":"Comments \u0026 Caveats","$t":""},{"index":"G","name":"Contact","$t":"Petr Menzel"},{"index":"H","name":"Buy Link","$t":""}]},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6866281935735151190"},"published":{"$t":"2015-02-04T01:38:56.503Z"},"updated":{"$t":"2015-02-04T01:44:01.203Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-04T01:43:58.978Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Goals For The Origin Info Bubble"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIntroduction\u003c/span\u003e\u003c/h2\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis is the Origin Info Bubble (OIB):\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cimg alt\u003d\"pib.png\" height\u003d\"523px;\" src\u003d\"https://lh3.googleusercontent.com/Mer74TWIss5I4pOWvFO5ctkZMqgOXElTD5J6opl3IF1cE_oWe2xI2yRIXk4E8_odc6UsJWQ58N0klaWMcEnau1_GnGPSlFP6lFYUUm-5Jnqz-GPWXeJqJWXK4simmsgpN6U\" style\u003d\"border:1px solid #000000\" width\u003d\"329px;\" /\u003e\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAs you can see, it has a lot of stuff in it, with 2 tabs to hold 2 (arguably 3: site data, permissions, and connection state) broad categories of information and controls about what the origin is and what it can do.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe are pretty sure the OIB does not show \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eall and only\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e the information and controls that users need to understand and control an origin.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eI believe the purpose of the OIB is to allow users to understand and control the origin. It was previously called the Page Info Bubble (PIB), but in this document I’ll use the more accurate name.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSince the OIB is the primary UI surface for control of an origin’s power, it enables the increased appification of the web platform. It is thus very important that we make it readily understandable and usable. See also \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d421248\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ehttps://code.google.com/p/chromium/issues/detail?id\u003d421248\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/span\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Possible-Goals\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ePossible Goals\u003c/span\u003e\u003c/h2\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eOne can imagine the OIB serving a variety of purposes, including at least display or control of:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eInformation about the permissions/capability grants/special powers\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e an origin has\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eInformation about the transport security state of the origin\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAuthenticated + confidential; partially authenticated + confidential; unauthenticated or broken authentication or not confidential\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIf authenticated: the certificate chain\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eOr a control to launch the certificate viewer or other developer/operator debugging information\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIf authenticated: extra authentication information\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCertificate Transparency status\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eKey pinning information\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eControls to set user-defined authentication policy:\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAccept this certificate\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ePin to the key(s) in this certificate chain\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e… \u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe origin’s name\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHistorical context for the user’s past interaction with the origin\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e# times visited in some period\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003edownloads\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ebookmarks\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ewhen or how often the origin has invoked powerful grants/APIs\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e… \u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eData the browser is storing locally for the origin\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ecookies\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eLocalStorage\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e…\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSummary (storage quota, et c.)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eProcesses the browser is running locally for the origin\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eService Workers\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eGeofences\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eTotal/average/peak battery cost of this origin\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e…\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhich extensions (if any) can access the origin\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eOthers? Surely I’m forgetting something.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eObviously there’s no way we can really show/afford control of all that information. That is especially true on small screens, but even on a large screen it would be a crowded and overwhelming interface. (It already is.) Therefore, we have to pick the most important and contextually-relevant information and controls.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe could and should choose what to show in the OIB based on context. For example, we could only show those grants that differ from the profile-wide defaults; we might never show certain marginal grants or content settings in the OIB; we might treat local storage quotas as a grant (iff the origin is about to exceed some profile-wide default); and so on.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Non-Goals\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNon-Goals\u003c/span\u003e\u003c/h2\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIt is a non-goal to show all possible information and controls about an origin in the OIB. We are assuming, probably correctly, that the OIB cannot be both complete and usable. Since the OIB is so important, we should trade off in favor of usability over completeness where there is a conflict.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Current-Goals\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCurrent Goals\u003c/span\u003e\u003c/h2\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis section describes the current goals for Chrome on desktop platforms (including ChromeOS, but possibly not Athena). For information about the OIB on non-desktop platforms, see \u003c/span\u003e\u003ca href\u003d\"https://docs.google.com/document/d/12PoBVo0D331RqnzVJwI8zbFU1hMs-ZcXcjqqwkG-6nc/edit#heading\u003dh.fumazaednf88\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNon-Desktop Platforms\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, below.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Show-The-Origin-Name\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eShow The Origin Name\u003c/span\u003e\u003c/h3\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe should use the OIB to show the origin name in an unambiguous, human-meaningful way. (As described in \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/Home/chromium-security/enamel\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ePresenting Origins To Users\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor origins whose hostnames have many labels we should show at least the effective TLD + 1 label. (We call this “eTLD + 1”.) For example if the full hostname is “a.b.c.pants.shoes.socks.wrists.co.jp” the eTLD (as determined by the \u003c/span\u003e\u003ca href\u003d\"https://publicsuffix.org/\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ePublic Suffix List\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e) is co.jp; that + 1 label (“wrists”) yields “wrists.co.jp”. Although not technically exact — a.b.c.pants.shoes.socks.wrists.co.jp is distinct from a.b.c.skirts.shoes.socks.wrists.co.jp — eTLD + 1 strikes a reasonable balance between correctness and understandability.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor origins whose hostnames are very long, due to a proliferation of labels or of extremely long labels\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, we should again the show eTLD + 1. If there is not room enough to show eTLD + 1, we should label the origin as possibly phishy and/or having broken authentication. (Rationale: Even if the authentication is perfectly good from a certificate or cryptographic perspective, it’s not good enough if we can’t show it to users on the screen.)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Show-The-Summarized-Origin-Security-State\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eShow The Summarized Origin Security State\u003c/span\u003e\u003c/h3\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe assume that only developers and operators are likely to be interested in the page-load’s \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ecomplete security state\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe complete security state of a page-load is:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;margin-left:48px;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eX.509 certificate chain;\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;margin-left:48px;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCertificate Transparency status;\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;margin-left:48px;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eTLS and X.509 cryptographic parameters; and\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;margin-left:48px;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ekey pinning status.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSince the OIB should be a primary UX surface for normal users, it should show only:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ea tri-state security indicator\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e (“Good”: authenticated + confidential; “Dubious”: partially authenticated + confidential; “Bad”: unauthenticated or broken authentication or not confidential); and\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ea control to launch a full view of the security state.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe full view of the security state must show the complete security state as defined above. It may also afford users control over key pinning and HSTS policy (currently available only in chrome://net-internals/#hsts) and control over trust in invalid certificate chains (as becomes necessary when a user opts to proceed through a \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCERT_INVALID\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e warning).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Afford-Control-Of-The-Origin-s-Special-Grants\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAfford Control Of The Origin’s Special Grants\u003c/span\u003e\u003c/h3\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBy \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003especial grants\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, I mean grants that the user has affirmatively changed from the profile-wide defaults.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNote that if the profile-wide defaults change — because the user changed them in chrome://settings/content or some future equivalent interface — then previously “non-special” grants become effectively special, and we should consider showing them in the OIB. For example, in a fresh profile the default grant for geolocation is Ask. If a user visits maps.google.com and opts to Always give that origin full access to the geolocation API, maps.google.com now has a special grant. Assuming the user has not changed it, \u003c/span\u003e\u003ca href\u003d\"http://www.bing.com\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ewww.bing.com\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e has the default grant and we might not show it in the OIB. If the user later changes the default to always allow origins full access to the geolocation API, the special grant to maps.google.com becomes effectively non-special, and we might choose not to show it in the OIB. The default grant to \u003c/span\u003e\u003ca href\u003d\"http://www.bing.com\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ewww.bing.com\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e remains non-special (even though the actual grant has changed), and we might choose to continue not to show it in the OIB.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFull control over all grants to the origin probably cannot fit in the OIB. Therefore it should be relegated to a secondary interface such as chrome://settings/content (or some future equivalent interface).\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6333507778373553020"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/enamel/goals-for-the-origin-info-bubble"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6866281935735151190"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6866281935735151190"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6866281935735151190"}],"author":[{"name":{"$t":"Chris Palmer"},"email":{"$t":"palmer@chromium.org"}}],"sites$pageName":{"$t":"goals-for-the-origin-info-bubble"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6923268419044203012"},"published":{"$t":"2012-08-13T21:01:49.021Z"},"updated":{"$t":"2015-02-03T19:19:39.312Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-02-03T19:19:37.851Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Dynamic Test Suites"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"font-family:Times New Roman\"\u003e\u003ch2 style\u003d\"font-size:medium;font-weight:bold\"\u003e\u003ca name\u003d\"TOC-Autotest-Dynamic-Test-Suites\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAutotest Dynamic Test Suites\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe next iteration of CrOS testing in Autotest is more dynamic and requires fewer manual changes with respect to adding and disabling tests.  The first pass at this required suites to be manually defined by hardcoding a list of tests, and added infrastructure to find a set of machines on which to run those tests. The former required manual management, and the latter can already be done by appropriately using autotest. Dynamic suites, in contrast, are defined by looking over all existing control files at runtime, and rely on the autotest infrastructure to shard the tests across all available, appropriate machines.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs far as someone scheduling a BVT run is concerned, sending an RPC to the autotest frontend telling it to schedule ‘control.bvt’ for a certain build on a certain board is sufficient; all other logic exists inside of the Autotest frontend (AFE).\u003c/span\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"font-size:medium;font-weight:bold\"\u003e\u003ca name\u003d\"TOC-Detailed-Design\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDetailed Design\u003c/span\u003e\u003c/h3\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-size:medium;font-weight:bold\"\u003e\u003ca name\u003d\"TOC-Specifying-job-dependencies\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSpecifying job dependencies\u003c/span\u003e\u003c/h4\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-size:medium\"\u003e\u003ca name\u003d\"TOC-This-is-how-a-single-test-specifies-the-kind-of-machine-on-which-it-can-be-run.-DEPENDENCIES-is-just-a-list-of-labels.-A-machine-satisfying-all-of-them-must-be-found-in-order-for-the-job-to-be-successfully-scheduled.DEPENDENCIES-CDMA-POWER-GOBI3K-X86-All-c\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis is how a single test specifies the kind of machine on which it can be run.  DEPENDENCIES is just a list of labels.  A machine satisfying all of them must be found in order for the job to be successfully scheduled.\u003c/span\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDEPENDENCIES\u003d‘CDMA’, ‘POWER’, ‘GOBI3K’, ‘X86’\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAll current tests need to be re-evaluated and updated to encapsulate required dependencies. e.g. GSM, CDMA, POWER, GOBI3K, BLUETOOTH etc etc.  For architecture-dependent tests, we can also include labels like ARM, TEGRA2, TEGRA3, X86, etc.\u003c/span\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h4\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-size:medium;font-weight:bold\"\u003e\u003ca name\u003d\"TOC-Board-compatibility\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBoard compatibility\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe ultimately decided against specifically expressing which boards a test should and should not run on.  We couldn’t come up with a reason we’d need to avoid a specific board or class of boards that could not be expressed with DEPENDENCIES.  Bluetooth tests don’t apply to Alex?  Well, no Alex device will have BLUETOOTH.  ACPI tests don’t apply to ARM?  Well, they’ll DEPEND on x86. \u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eInstead, we will rely on dynamic_suite code in the AFE to distinguish between a test that has unsatisfiable dependencies at the time of scheduling, and one that can be scheduled, but does not run in the time allotted.  In the latter case, the job will be ABORTed.  In the former case, we will fail the test with TEST_NA.  In the Alex case above, for example, all tests with a BLUETOOTH dep will be TEST_NA.  As a more complicated example, consider a GOBI3K test on Mario, and assume we have only one Mario with that modem in it.  If all is well, the test can be scheduled in the time allowed and things are good.  If the device is down, the AFE still knows that it should have a machine that meets the test’s DEPENDENCIES, but discovers that the device is not currently ready.  That’s fine, and it schedules the test.  When the time allotted for the suite is up, the test would be ABORTed and included as a failure in the test results. \u003c/span\u003e\u003cbr /\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-size:medium;font-weight:bold\"\u003e\u003ca name\u003d\"TOC-Job-reporting\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eJob reporting\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor TPM’s, one can provide a view of test results per-build-per-board that shows all jobs that could be scheduled, and the results of those tests.  Specifically, jobs that are TEST_NA can be ignored if the customers of the dashboard so-desire.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor the lab team, we can show all jobs that we tried to schedule, so that we can see which jobs are getting starved and detect new, unexpected starvation.\u003c/span\u003e\u003cbr /\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-size:medium;font-weight:bold\"\u003e\u003ca name\u003d\"TOC-Defining-suites\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDefining suites\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cspan style\u003d\"font-size:15px\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times New Roman\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cspan style\u003d\"font-size:15px\"\u003e*** For more updated information, please see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/dynamic-suite-codelab\"\u003eDynamic Suites Code Lab\u003c/a\u003e.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times New Roman\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cspan style\u003d\"font-size:15px\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003eWe've added a custom variable to control files called SUITE. SUITE can contain a comma-delineated list of arbitrary strings. Only suite names that have an associated control file will actually be usable in any meaningful way. By convention, we put all suite control files in a top-level directory called 'test_suites', and name the files appropriately. For example, \u003c/span\u003e\u003ccode\u003e\u003cfont color\u003d\"#38761d\" size\u003d\"3\"\u003etest_suites/control.bvt\u003c/font\u003e\u003c/code\u003e\u003cspan style\u003d\"font-size:15px\"\u003e is the control file for the BVT suite.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis does require parser changes, and does make including upstream tests in our suites a bit complex.  The former is not that difficult (and probably upstreamable).  We could likely address the latter by adding a level of control-file-indirection, and having a site-specific file that uses SUITE and references the upstream test.\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe use the already-existing “EXPERIMENTAL” flag to mark tests as candidates for inclusion in a suite, and will run them along with the non-experimental tests -- but tag them separately so that results can be separated out in the final report.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe considered making \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eall\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e test suites a query of sorts over the labels defined in control files (the BVT would be all SHORT, functional tests that are not experimental, for example), which would avoid these issues, but decided that this smacked too much of magical side effects for use in our primary test suites.  However, we will provide a library of code that teams can use to create their own suite control files.  For example, ‘kernel.soak’ could simply be a one-liner that found and scheduled jobs for all SHORT, MEDIUM, and LONG functional and stress tests in the “kernel” category.\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium\"\u003e\u003ca name\u003d\"TOC-The-code\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe code\u003c/span\u003e\u003c/h3\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Scheduling-a-suite-for-a-given-board-and-image\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eScheduling a suite for a given board and image\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe defined a new autotest RPC for this, with the following interface:\u003c/span\u003e\u003c/b\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline\"\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003edef create_suite_job(suite_name, board, build, pool, check_hosts\u003dTrue,\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e                     num\u003dNone, file_bugs\u003dFalse, timeout\u003d24, timeout_mins\u003dNone,\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e priority\u003dpriorities.Priority.DEFAULT,\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e suite_args\u003dNone, wait_for_results\u003dTrue):\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    \"\"\"\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    Create a job to run a test suite on the given device with the given image.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    When the timeout specified in the control file is reached, the\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    job is guaranteed to have completed and results will be available.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param suite_name: the test suite to run, e.g. 'bvt'.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param board: the kind of device to run the tests on.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param build: unique name by which to refer to the image from now on.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param pool: Specify the pool of machines to use for scheduling\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e            purposes.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param check_hosts: require appropriate live hosts to exist in the lab.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param num: Specify the number of machines to schedule across.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @param file_bugs: File a bug on each test failure in this suite.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e    @param timeout: The max lifetime of this suite, in hours.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e    @param timeout_mins: The max lifetime of this suite, in minutes. Takes\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e                         priority over timeout.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e    @param priority: Integer denoting priority. Higher is more important.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e    @param suite_args: Optional arguments which will be parsed by the suite\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e                       control file. Used by control.test_that_wrapper to\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e                       determine which tests to run.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e    @param wait_for_results: Set to False to run the suite job without waiting\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e                             for test jobs to finish. Default is True.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @raises ControlFileNotFound: if a unique suite control file doesn't exist.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @raises NoControlFileList: if we can't list the control files at all.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @raises StageBuildFailure: if the dev server throws 500 while staging build.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @raises ControlFileEmpty: if the control file exists on the server, but\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e                              can't be read.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    @return: the job ID of the suite; -1 on error.\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Courier New\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ccode\u003e    \"\"\"\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cdiv style\u003d\"font-family:Courier New;font-size:13px;font-weight:bold;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:medium\"\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;display:inline!important\"\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h4\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;background-color:transparent;font-size:15px;white-space:pre-wrap\"\u003e\u003cb\u003eChange priority:\u003c/b\u003e The arg priority is an integer denoting priority, used by our scheduler to decide how to prioritize jobs. You can find all valid priority options in autotest_lib.client.common_lib.priorities. Currently, the priority ladder looks like - Weekly \u0026lt; Daily \u0026lt;PostBuild \u0026lt; Default \u0026lt; Build \u0026lt; PFQ \u0026lt; CQ.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:15px;white-space:pre-wrap\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cb\u003eWait or not wait for results: \u003c/b\u003eUse the arg wait_for_results\u003dTrue/False to tell the suite job whether you want it to wait for all test jobs to finish or not. Not waiting for the results can reduce the load burden to our rpc server, so it is recommended whenever it is possible.\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:medium\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:medium\"\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;display:inline!important\"\u003e\u003ca name\u003d\"TOC-2\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h4\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:medium\"\u003e\u003ch4 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;display:inline!important\"\u003e\u003ca name\u003d\"TOC-Running-the-suite\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRunning the suite\u003c/span\u003e\u003c/h4\u003e\u003c/span\u003e\u003c/div\u003e\u003cb style\u003d\"font-size:medium;font-weight:normal\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecreate_suite_job() starts by telling the dev server to fetch the image to be tested, and its associated autotest bundle, from the URL provided.  \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eClients of autotest will no longer need to be aware of the dev server\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e.  The details of this may change going forward, but all this work will be handled by this RPC.  \u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOnce the image and autotest bundle are staged on dev server, it goes through all the control files associated with the build being tested, and schedule the proper jobs.  At that point, we let the autotest scheduler take responsibility for all the async scheduling/dependency scheduling. It is important that all jobs are scheduled via rpc calls with a name that associates them all together so that when we want to look at results we can aggregate them all in a query.  This will allow callers (like the buildbot-autotest connection) to poll for the status of all jobs kicked off by the BVT suite control file, and eventually find and gather up results for reporting purposes\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/dynamic-test-suites"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6923268419044203012"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6923268419044203012"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6923268419044203012"}],"author":[{}],"sites$pageName":{"$t":"dynamic-test-suites"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8079392522444790125"},"published":{"$t":"2012-09-26T17:03:57.021Z"},"updated":{"$t":"2015-01-30T21:10:33.796Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-30T21:10:30.722Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chrome API keys in the Chromium OS SDK chroot"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp\u003eWhen building Chromium on Chromium OS, there are (at least) 3 environments for building that are relevant.\u003c/p\u003e\r\n\u003col\u003e\u003cli\u003eThe host home directory.\u003c/li\u003e\r\n\u003cli\u003eThe home directory in the chroot.\u003c/li\u003e\r\n\u003cli\u003eThe home directory while building the chromeos-base/chromeos-chrome package.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cp\u003eThe mechanism for compiling API keys into the Chromium binary itself under Chromium OS uses copy-propagation between the layers.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Between-layers-1-2-host-chroot-\" /\u003eBetween layers 1 \u0026amp; 2 (host \u0026amp; chroot)\u003c/h3\u003e\r\n\u003cp\u003eThe enter chroot functionality takes care of propagating the keys.  If the file \u003ccode\u003e.googleapikeys\u003c/code\u003e is not present in the chroot, or is empty, the keys are searched for in your home directory, extracted and written there. It is a line-oriented file that should look like the sample in the chrome page.\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode\u003e'google_api_key': '\u003cb\u003eABC123\u003c/b\u003e',\u003cbr /\u003e\r\n'google_default_client_id':     '\u003cb\u003e123/abc\u003c/b\u003e',\u003cbr /\u003e\r\n'google_default_client_secret': '\u003cb\u003efloor-sweeper\u003c/b\u003e',\u003c/code\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eTo reset these the easiest way to update the chroot is simply:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cfont size\u003d\"2\"\u003e\u003ccode\u003ecros_sdk -- rm ../../../.googleapikeys\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cp\u003eand then the next time something enters the chroot, your native credentials will be copied in. If the keys are not working, try taking a look at the file to see if the format of your keys outside the chroot confused the propagation.\u003c/p\u003e\r\n\u003cp\u003eIf you want your chroot to build something non-default or non-shared, you can enter the chroot and change the \u003ccode\u003e.googleapikeys\u003c/code\u003e directly.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Between-layers-2-3-chroot-and-package-\" /\u003eBetween layers 2 \u0026amp; 3 (chroot and package)\u003c/h3\u003e\r\n\u003cp\u003e\r\nThe chromeos-base/chromeos-chrome ebuild takes care of respecting the keys in the chroots \u003ccode\u003e.googleapikeys\u003c/code\u003e in the final source build environment. It does this by expanding and converting the file into an include.gypi in the inside environment that does chromium's make.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1209459978548328160"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/building-chromium-browser/chrome-api-keys-in-the-chroot"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8079392522444790125"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8079392522444790125"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8079392522444790125"}],"author":[{"name":{"$t":"Peter Mayo"},"email":{"$t":"petermayo@chromium.org"}}],"sites$pageName":{"$t":"chrome-api-keys-in-the-chroot"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4075704472261714269"},"published":{"$t":"2015-01-30T18:24:24.859Z"},"updated":{"$t":"2015-01-30T18:24:24.859Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-30T18:24:24.859Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4075704472261714269"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4075704472261714269"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4075704472261714269"}],"author":[{"name":{"$t":"Annie Sullivan"},"email":{"$t":"sullivan@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/a/chromium.org/document/d/1eCR2v9uR9jR-LQi2GiZ9soQmW4p8lfAFjj-uewBGbh8/edit#heading\u003dh.cg9oxhygkrer\"\u003eNo data from some android bots on chromium.perf for 2 weeks\u003c/a\u003e"},{"index":"B","name":"Date","$t":"2014-12-22"}]},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/403194395084517733"},"published":{"$t":"2015-01-30T18:23:56.164Z"},"updated":{"$t":"2015-01-30T18:23:56.164Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-30T18:23:56.164Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/403194395084517733"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/403194395084517733"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/403194395084517733"}],"author":[{"name":{"$t":"Annie Sullivan"},"email":{"$t":"sullivan@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/document/d/1MnSceOmgw5VPgegNWaMV5iakrvRROeVYw6P0FXvvC28/edit\"\u003echromium.perf tests on android userdebug builds failing for 7 days\u003c/a\u003e"},{"index":"B","name":"Date","$t":"2015-01-30"}]},{"gd$etag":"\"XSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"},"published":{"$t":"2015-01-05T23:49:06.257Z"},"updated":{"$t":"2015-01-29T18:30:34.047Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-29T18:30:32.929Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"USB Type-C to HDMI Adapter"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:500px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-2\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOverview\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Hardware-Capabilities\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eHardware Capabilities\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware-Source-Code\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware Source Code\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Building-Firmware\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eBuilding Firmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Flashing-Firmware\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eFlashing Firmware\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Connecting-to-the-Adapter\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eConnecting to the Adapter\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h2\u003e\r\n\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003eThe USB Type-C to HDMI Adapter connects a USB Type-C plug to an HDMI receptacle. It enables users of any Chrome device that implements\u003cspan style\u003d\"background-color:transparent\"\u003e USB-Type C \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eto connect to an HDMI display. \u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Hardware-Capabilities\" /\u003eHardware Capabilities\u003c/h2\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThis adapter\u003c/span\u003e\u003cspan style\u003d\"font-size:13px;color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent\"\u003e is an implementation of a USB Type-C DFP_D to HDMI Protocol Converter. \u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13.3333339691162px;background-color:transparent\"\u003eIt follows the requirements of section 4.3.1 of the VESA\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13.3333339691162px\"\u003e DisplayPort Alt Mode for USB Type-C Standard\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13.3333339691162px;background-color:transparent\"\u003e. I\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:transparent\"\u003en the VESA standard, refer to \u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:transparent\"\u003eFigure 4-13: Scenario 3a. \u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px;background-color:transparent\"\u003eIt provides the following features:\u003c/span\u003e\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eDisplayPort protocol conversion to support HDMI \u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eautomatic enabling of video out\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003evideo output with resolutions of \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333339691162px\"\u003eup to 4K @ 60 Hz (depending on system and monitor capabilities)\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-1\" /\u003e\r\n\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/hoho/HoHo%20Block%20Diagram%20%281%29.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"316\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1420767555760/chromium-os/hoho/HoHo%20Block%20Diagram%20%281%29.png\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\r\n\u003c/h3\u003e\r\n\u003cdiv\u003eFor schematics, \u003ca href\u003d\"https://docs.google.com/a/chromium.org/viewer?a\u003dv\u0026amp;pid\u003dsites\u0026amp;srcid\u003dY2hyb21pdW0ub3JnfGRldnxneDoyZWUwYmU2NWNiMWMwZTY2\"\u003eclick here\u003c/a\u003e or see the attached file.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware-Source-Code\" /\u003eFirmware Source Code\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe firmware is located In the Chromium Embedded Controller repository under \u003c/span\u003e\u003ci style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/platform/ec/+/master/board/hoho/\"\u003eboard/hoho/\u003c/a\u003e\u003c/i\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e :\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003e\u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/platform/ec/+/master/board/hoho/\"\u003ehttps://chromium.googlesource.com/chromiumos/platform/ec/+/master/board/hoho/\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Building-Firmware\" /\u003eBuilding Firmware\u003c/h3\u003e\r\n\u003cdiv\u003eWithin your Chromium OS chroot, the syntax is:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003ecd ~/trunk/src/platform/ec\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003emake BOARD\u003dhoho\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Flashing-Firmware\" /\u003eFlashing Firmware\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333339691162px\"\u003eThe firmware is normally flashed via the kernel, as part of the Chrome OS Auto-Update process. Payloads are located in \u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333339691162px;font-family:Arial;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003ccode\u003e/lib/firmware/cros-pd\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:13.3333339691162px\"\u003e.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333339691162px\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWhen the adapter is connected to a Chrome device, you can manually flash the read-write firmware as follows:\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003ccode\u003eectool --cros_pd flashpd 4 \u0026lt;port\u0026gt; /tmp/hoho.ec.RW.bin\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe device must be in developer mode to run the \u003ccode\u003eectool\u003c/code\u003e command. After running this command, the firmware is located in \u003ccode\u003e~/trunk/src/platform/ec/build/hoho/ec.bin .\u003c/code\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Connecting-to-the-Adapter\" /\u003eConnecting to the Adapter\u003c/h2\u003e\r\n\u003cp\u003eDevelopers of devices based on this design may need to install an initial image by putting the STM32F072 into DFU mode. This can be done by asserting PD_BOOOT0 (TP11 in the schematic) and resetting the MCU. It can be helpful to attach a switch for this purpose on prototype devices. \u003c/p\u003e\r\n\u003cp\u003eInstalling an image requires the dfu-util tools package on the Chrome device where the adapter is connected. To deploy dfu-util and copy the chromeos-ec image from within your Chromium OS chroot, the syntax is:\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"font-size:13.3333339691162px;line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-size:13.3333339691162px\"\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(56,118,29);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont size\u003d\"3\"\u003eBOARD\u003d\u003ci\u003eboard-name\u003c/i\u003e\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(56,118,29);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont size\u003d\"3\"\u003eIP\u003d\u003ci\u003ehost-IP-address\u003c/i\u003e\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(56,118,29);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont size\u003d\"3\"\u003eemerge-${BOARD} dfu-util chromeos-ec\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(56,118,29);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont size\u003d\"3\"\u003ecros deploy $IP dfu-util chromeos-ec\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(56,118,29);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont size\u003d\"3\"\u003escp ~/trunk/src/platform/ec/build/hoho/ec.bin root@${IP}:/tmp/.\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\u003cbr style\u003d\"font-size:13.3333339691162px;line-height:normal\" /\u003e\r\n\u003c/p\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003ewhere \u003ci\u003eboard-name\u003c/i\u003e is the name of the Chrome device, for example peppy, and \u003ci\u003ehost-IP-address\u003c/i\u003e is its IP address on the network.\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003eThe next step is to connect the adapter to the Chrome device in DFU mode and write a full image (RO + RW). On the Chrome device, the syntax is:\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:36pt\"\u003e\r\n\u003c/p\u003e\r\n\u003cdiv style\u003d\"font-size:13.3333339691162px\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eflash_ec --board\u003dhoho --image\u003d/tmp/ec.bin\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/593897542665142458"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/hoho"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6186844832924451598"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"}],"author":[{}],"sites$pageName":{"$t":"hoho"},"sites$revision":{"$t":"14"}},{"gd$etag":"\"WSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8919585140916925404"},"published":{"$t":"2010-07-14T21:21:47.296Z"},"updated":{"$t":"2015-01-24T01:22:11.431Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2012-11-07T21:02:19.705Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Native Client Coding Style Guidelines"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eThe purpose of this document is to codify our existing coding style guidelines for new Native Client project members, including external committers.  Some of the recommendations address security concerns, e.g., making the code easier to audit.  A core principle is that our coding style should encourage writing correct code.  Moreover, it should encourage writing obviously correct, easily audited code.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eGenerally, we follow the published Google Coding Style guidelines.  However, those guidelines were written primarily for C++ and python code, and a portion of NaCl code is in C (esp kernel-like code); furthermore, we use scons/gyp/subversion rather than gconfig/perforce, so build system issues are also addressed.  Additionally, we incorporate/use bodies of third party code or their interfaces, most obvious of which is NPAPI, and stylistic differences occur, especially among major modules.  In such cases, it is generally a good idea to adhere to the existing style -- for example, the Google Coding Style expressly does not endorse one position of the space in declarations such as \u003cfont face\u003d\"'courier new', monospace\"\u003echar *p;\u003c/font\u003e versus \u003cfont face\u003d\"'courier new', monospace\"\u003echar* p;\u003c/font\u003e over another -- and in such cases maintaining consistency with the prevalent style in the module would enhance readability.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe Google C++ coding style guide can be found here: \u003ca href\u003d\"http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml\" target\u003d\"_blank\"\u003ehttp://google-styleguide.googlecode.com/svn/trunk/cppguide.xml\u003c/a\u003e; the python version can be found here: \u003ca href\u003d\"http://google-styleguide.googlecode.com/svn/trunk/pyguide.html\" target\u003d\"_blank\"\u003ehttp://google-styleguide.googlecode.com/svn/trunk/pyguide.html\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:medium\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:medium\"\u003eC/C++/Build Style Rules\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eIn a file that implements an interface declared in a header file, always include that header file.  Rationale: this prevents interface / implementation mismatches, since C does not do C++ style name mangling to encode the parameter types in the linker-level name.  Even in C++, since the return type is not part of the type signature, return type mismatches would not get detected as a side-effect of name mangling.\u003c/li\u003e\u003cli\u003eHeader files have guards against multiple inclusion.  Rationale: unlike traditional Unix system header file style, the user of a header file is not responsible for knowing what type declarations etc that the header file may transitively require and to put include directives for transitively dependent header files in the C/C++ file ahead of the desired header file.  Instead, the Google style is that if a header file A depends on something in header file B, then A should include B.  If a source file also needs something from B, it will explicitly include B again.  Do \u003ci\u003enot\u003c/i\u003e depend on knowledge about A's implementation -- i.e., that it would include B -- in the source file, since that's an implementation detail that may change.  Always directly include all header files that are needed by a file, but do not \"look inside\" files that you include: do not depend on transitive inclusions.\u003c/li\u003e\u003cli\u003eAt the same time try to reduce the number of other header files your header depends on. If you only use a class/struct via pointers/references a simple forward declaration will  do. Similarly you may want think twice before making a class contain another class as a member. Often using a pointer/reference will provide better information hiding at the price of an extra indirection (along with memory allocation and associated error handling).\u003c/li\u003e\u003cli\u003eDon't turn off compiler warning flags.  If you have to, e.g., because we absolutely have to include a third party file, clone the scons build environment and remove the compiler warning flag only for that cloned environment, and use that cloned environment only for those files that includes the third party header file.  Be judicious and limit the amount of taint as much as possible.\u003c/li\u003e\u003cli\u003eWhen importing third party code, rather than turning off warnings broadly (e.g., removing \u003cfont face\u003d\"'courier new', monospace\"\u003e-pedantic\u003c/font\u003e or \u003cfont face\u003d\"'courier new', monospace\"\u003e-Wall\u003c/font\u003e), try to turn off only the warning that the third party code triggers, e.g., \u003cfont face\u003d\"'courier new', monospace\"\u003e-Wno-long-long\u003c/font\u003e.  Limit the scope.\u003c/li\u003e\u003cli\u003eDo not declare function prototypes in \u003cfont face\u003d\"'courier new', monospace\"\u003e.c\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e or \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e.cc\u003c/font\u003e files -- include the corresponding header file.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:medium\"\u003eC Style Rules\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eWe implement objects in C via explicit ctor and virtual function tables.  Unlike C++, the ctor function returns an int -- conceptually a bool -- indicating success with a non-zero value.  In C++ this would be split into a simple ctor that fills in fields with default values so dtor cleanup can happen, and an explicit Init function that handles the more complex initialization that may return an error.\u003c/li\u003e\u003cli\u003eIn ctors, we always start by setting the vtbl pointer to NULL.  This is a defense-in-depth mechanism.  Only when the ctor is about to return success is the vtbl pointer set to point at a valid virtual function table.  This means that should the caller forget to check the return value of the ctor, the next use of a virtual function will cause the program to abort due to the NULL pointer de-reference.  In C++ code this would have to be emulated with a boolean flag that is set only when the Init member function returns success, and where every virtual function explicitly checks the flag upon entry. We generally use placement-new style ctors, where the caller allocates the memory (either stack or heap) and pass the memory to the ctor.  Note that in ctors of derived classes, we may have to explicitly reset vtbl pointers if the ctor of the base class succeeds but later initialization of (new) members fail -- in order for the derived class ctor to fail cleanly, it should destroy any already initialized new members, then call the base class dtor -- which should reset the vtbl pointer anyway -- as the last operation before returning failure (0).\u003c/li\u003e\u003cli\u003eIn base class dtors, we always end with setting the vtbl pointer to NULL.  It doesn't hurt to also explicitly set them to NULL as the last operation in derived class dtors either; depending on the frequency of object construction/destruction, it may even make sense to explicitly clear the entire object's memory.  Rationale: this prevents uses -- via virtual functions -- of objects that have been deleted (object reuse).\u003c/li\u003e\u003cli\u003eUse standard safety idioms.  The principle here is that it should be obvious that the code is correct.  A code auditor/reviewer should not have to hunt far away for type declarations or for constants to determine the correctness of the code.  Sometimes it's better to have redundant checks, i.e., integer overflow checks just above the allocation, even though the value was checked earlier against another value so that the earlier check's post-condition would entail that the overflow check is unnecessary.\u003c/li\u003e\u003cul\u003e\u003cli\u003eInteger overflow checks:  use SIZE_T_MAX, which is (~((size_t) 0)), to verify that allocating several objects will not cause an overflow:\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e/* num_elt is untrusted */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eif (num_elt \u0026gt; SIZE_T_MAX / sizeof *ptr) {\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  /* error handling / abort */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eptr \u003d malloc(num_elt * sizeof *ptr);\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eif (NULL \u003d\u003d ptr) {\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  /* error handling */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003esimilarly, even assignments can cause problems:\u003c/span\u003e\u003cbr /\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003eint32_t len \u003d strlen(some_c_str);  /* on 64-bit systems, a problem also with int64_t */\u003c/span\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003ehere, since \u003c/span\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003estrlen\u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e returns a value of type \u003c/span\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003esize_t\u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e, it may be a value that cannot be represented as an \u003c/span\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eint32_t\u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e -- according to the C (and C++) standard, when such an assignment occurs and the expression value is not representable in the destination type, the result is implementation dependent.  And when this occurs, compilers are free to generate code that delete all of the users' files (though we know of no such compiler!).  Instead, check:\u003cbr /\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003esize_t len_sz \u003d strlen(some_c_str);\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eif (len_sz \u0026gt; INT32_MAX) {  /* from stdint.h */\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  /* error handling */\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e}\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003elen \u003d (int32_t) len_sz;  /* len_sz unused henceforth, so this is just renaming a register / memory location */\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eto ensure that overflows won't cause problems.  Similarly, even additions can overflow:\u003cbr /\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003ei\u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ent32_t foo;\u003cbr /\u003eint32_t bar;\u003cbr /\u003e...\u003cbr /\u003efoo \u003d bar + 1;\u003c/font\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eshould be\u003cbr /\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eint32_t foo;\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eint32_t bar;\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e...\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eif (bar \u0026gt; INT32_MAX - 1) {\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  /* error handling */\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e}\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003efoo \u003d bar + 1;\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cul\u003e\u003cul\u003e\u003cli\u003eSee the malloc idiom above.  The amount of memory to be allocated should always use a dereference of the left-hand-side of the assignment, since the lhs must be of the right type.  Rationale: if for some reason we later change the type of a variable, there is no need to track down occurrences of sizeof(Typename) elsewhere, since the use of the lhs in the sizeof will make it automatically correct.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003eComparisons involving a constant should keep the constant on the lhs of the comparison operator.  This avoids accidents like\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eif (ptr \u003d NULL) {\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  /* oops */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003ewhere a comparison gets turned into an assignment (followed by implicit comparison to 0) due to a typographical error, changing the meaning of the code.  Instead, use the idom from the larger code snippet above.  Since the lhs is not an lvalue, this cannot be accidentally turned into an assignment.  While not a strict requirement, constants should be used on the lhs even for inequality tests, since in the future somebody else might change things around and turn it (or via cut-n-paste) into an intended equality test.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOnce we have a test to ensure that we do not accidentally turn off compiler-specific flags that warn when constructs like \u003cfont face\u003d\"'courier new', monospace\"\u003eif (lvalue \u003d expression)\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e is used in code, we can relax this rule.\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cul\u003e\u003cul\u003e\u003cli\u003eRather than refering to a distantly defined value/variable such as a constant defined in a header or the top of the file\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e#define BUFFER_SIZE 1000\u003c/span\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e/* ... */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003echar buffer[BUFFER_SIZE];\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e/* ... */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ememset(buffer, 0, BUFFER_SIZE);  /* bad */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003einstead, do\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ememset(buffer, 0, sizeof buffer);  /* better (Yes, the parentheses are not required around buffer here.  It surprised cbiffle and sehr too.) */\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003eThe latter is more obviously correct.  (But not if buffer is actually a char * to malloc'd memory, so auditors still have to do some looking around.)\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cul\u003e\u003cul\u003e\u003cli\u003eadd more lines...\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eadd more lines...\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-C-Style-Rules\" /\u003e\u003cb\u003eC++ Style Rules\u003c/b\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eWe generally match the Google style rules.  Differences are generally due to our code not being standard Google C++ code and not running in the production environment found in Google datacenters.\u003c/li\u003e\u003cli\u003eExceptions:\u003c/li\u003e\u003cul\u003e\u003cli\u003eNote that Chromium's default gyp file setup compiles with \u003cfont face\u003d\"'courier new', monospace\"\u003e-fno-exceptions\u003c/font\u003e so \u003cfont face\u003d\"'courier new', monospace\"\u003ecatch\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e statements have no effect -- the \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ecatch\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e block is just dead code, and the C++ runtime provided top-level exception handler will be the only exception handler that's active. \u003c/font\u003e\u003c/li\u003e\u003cli\u003eIf for some reason we must use exceptions or deal with exceptions (e.g., because we are building a library/module that will be generally useful and is not NaCl specific or must use an underlying library that throws exceptions as part of its API), do not throw exceptions across API boundaries (except for fatal errors).  The library/module \u003ci\u003emust\u003c/i\u003e be compiled with exceptions enabled, but the relying code might not, and we should not, in general, force relying code to enable exceptions.  This usually means that the library must catch all (non-fatal) exceptions at API boundaries and convert them into error codes.  Use idioms that encourage exception safety, particularly when interacting with STL.  See Effective C++ item #29.\u003c/li\u003e\u003cli\u003eRemember that \u003cfont face\u003d\"'courier new', monospace\"\u003enew\u003c/font\u003e can throw.  You must either (1) assume that an exception can cause a jump at any invocation of \u003cfont face\u003d\"'courier new', monospace\"\u003enew\u003c/font\u003e -- and cause the application to abort -- or (2) use \u003cfont face\u003d\"'courier new', monospace\"\u003enew(std::nothrow)\u003c/font\u003e and check its result!  Unlike production code where failing fast is generally a good idea to either failover to another machine or to restart the local server process, this is sometimes not appropriate in client-side code.\u003c/li\u003e\u003cul\u003e\u003cli\u003eNote that neither of these is inherently safer than the other.  While \u003cfont face\u003d\"'courier new', monospace\"\u003enothrow\u003c/font\u003e may seem safer because of the lack of surprise control flow, at least an exception causes destructors in the current scope to be run, while failing to check for a null pointer will simply segfault down the line (at best).\u003c/li\u003e\u003cli\u003eWhen allocating a series of objects in the heap, use scoped_ptr or auto_ptr to cleanly deallocate them if one new or constructor throws.  This is also good RAII practice.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cli\u003eIf a data structure's size may be determined by a malicious author — say, a set describing all the validation errors encountered in a NaCl module — expect exceptions like bad_alloc that indicate you are being DoS'd.  To avoid having to reason about exception safety and failure modes in these cases, consider capping the size of such structures.\u003c/li\u003e\u003cli\u003eBeware of integral type conversions, especially when dealing with inputs from external sources that might be under an attacker's control.  Use \u003cfont face\u003d\"'courier new', monospace\"\u003eassert_cast\u0026lt;T\u0026gt;(expr)\u003c/font\u003e and \u003cfont face\u003d\"'courier new', monospace\"\u003esaturate_cast\u0026lt;T\u0026gt;(expr)\u003c/font\u003e from \u003cfont face\u003d\"'courier new', monospace\"\u003enative_client/src/include/check_cast.h\u003c/font\u003e when appropriate.  For example:\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ebool SanityCheckerApi(SomeType obj, char* data, int32_t nbytes);\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ebool SomeClass::SomeMethod(std::string s) {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  if (SanityCheckerApi(obj_, s.c_str(), static_cast\u0026lt;int32_t\u0026gt;(s.size()))) {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e     // Compilers correctly warn that precision is lost without a cast,\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e     // since std::string::size() is size_t, and on a 64-bit machine is\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e     // large than int32_t.  However, just using a static_cast\u0026lt;int32_t\u0026gt; to\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e     // get rid of the compiler warning messages is wrong.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e     return false;  // error\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  }\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  /* Use all of s */\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  return true;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ecan cause a security problem: if the caller-supplied data \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003es\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e is under the adversary's control and could be more than 4GB in size, then \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003eSanityCheckerApi\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e will only check the first \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003es.size() mod 2**32\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e bytes of data, and the use of \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003es\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e after the check will (presumably) consume all of \u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003es\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e and do the wrong thing.\u003c/font\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eadd more here...\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663733556794389665"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/styleguide"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8919585140916925404"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8919585140916925404"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8919585140916925404"}],"author":[{}],"sites$pageName":{"$t":"styleguide"},"sites$revision":{"$t":"10"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5548930097806777862"},"published":{"$t":"2010-07-12T21:48:54.319Z"},"updated":{"$t":"2015-01-23T22:17:06.563Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-07-12T22:01:56.278Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"2: How Tos"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cimg src\u003d\"http://www.google.com/chart?chc\u003dsites\u0026amp;cht\u003dd\u0026amp;chdp\u003dsites\u0026amp;chl\u003d%5B%5BPage+listing'%3D20'f%5Cv'a%5C%3D0'10'%3D499'0'dim'%5Cbox1'b%5CF6F6F6'fC%5CF6F6F6'eC%5C0'sk'%5C%5B%22Subpage+Listing%22'%5D'a%5CV%5C%3D12'f%5C%5DV%5Cta%5C%3D10'%3D0'%3D500'%3D297'dim'%5C%3D10'%3D10'%3D500'%3D297'vdim'%5Cbox1'b%5Cva%5CF6F6F6'fC%5CC8C8C8'eC%5C'a%5C%5Do%5CLauto'f%5C\u0026amp;sig\u003dlxEPbO98PQKCTIgDHMqrwU0hJD8\" data-type\u003d\"subpages\" data-props\u003d\"align:left;borderTitle:Subpage Listing;displayAs:gadget;maxDepth:6;rootPage:THIS_PAGE;\" width\u003d\"500\" height\u003d\"300\" style\u003d\"display:block;text-align:left;margin-right:auto;\" /\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663733556794389665"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/how-tos"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5548930097806777862"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5548930097806777862"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5548930097806777862"}],"author":[{}],"sites$pageName":{"$t":"how-tos"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8135152406277611922"},"published":{"$t":"2015-01-23T07:51:20.771Z"},"updated":{"$t":"2015-01-23T07:51:20.771Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-23T07:51:20.771Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/408337301204496940"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8135152406277611922"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8135152406277611922"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8135152406277611922"}],"author":[{"name":{"$t":"Daniel Kurtz"},"email":{"$t":"djkurtz@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Area","$t":"KMS / DRM"},{"index":"B","name":"Title","$t":"Atomic Modeset support for KMS drivers"},{"index":"C","name":"URL","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"http://blog.ffwll.ch/2014/11/atomic-modeset-support-for-kms-drivers.html\"\u003ehttp://blog.ffwll.ch/2014/11/atomic-modeset-support-for-kms-drivers.html\u003c/a\u003e"}]},{"gd$etag":"\"YDspeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8624588879735004767"},"published":{"$t":"2015-01-22T21:08:50.247Z"},"updated":{"$t":"2015-01-22T23:04:20.897Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-22T23:04:19.942Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Time Safety and Code Readability"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eAs someone that's written a ton of code using the src/base/time classes, and have made significant contributions in src/base/time, there are \"holes\" where these types can be too-easily used in semantically incorrect ways.  In addition, there are opportunities to improve readability.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eMy \"wish list\" for changes (live document) follows:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-One-C-class-for-each-Clock-Timeline\" /\u003eOne C++ class for each Clock/Timeline\u003c/h2\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ebase::Time represents values that have been sampled/computed from the local system calendar clock.  However, base::TimeTicks values may have come from several different clocks.  A recent bug revealed the mixing of values from different clocks was actually happening in the code base, and this was resolved via \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/797893003/\"\u003ehttps://codereview.chromium.org/797893003/\u003c/a\u003e.  The solution eliminated the possibility of having separate \"high-res\" versus \"low-res\" clock sources for TimeTicks.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eTwo other TimeTicks clock sources remain: \"ThreadNow\" time and \"SystemTrace\" time.  We should provide separate classes for these so that compile-time checking enforces semantically correct time math.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Eliminate-From-ToInternalValue-\" /\u003eEliminate From/ToInternalValue()\u003c/h2\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eCode throughout Chromium subverts the compile-time type-checking of time math by illegally using these public methods.  The code only works under an assumption that, internally, the time classes use a one-microsecond timebase with values stored internally in a 64-bit signed integer type.  The stated purpose of these methods is only to allow (de)serialization of the time types (e.g., for IPC), and \u003cb\u003enot\u003c/b\u003e to provide direct access to private members.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThese methods should be eliminated altogether and replaced with From/ToMicroseconds().  Code that (de)serializes time values should also simply use the From/ToMicroseconds() methods, since that is the highest-resolution timebase currently supported; and so (de)serialization can be performed without introducing any rounding error.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Fix-Time::is_null-and-TimeTicks::is_null-\" /\u003eFix Time::is_null() and TimeTicks::is_null()\u003c/h2\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThese methods make an incorrect assumption: That a zero-valued Time is the same as an \"unset\" or \"undefined\" Time.  However, this has caused bugs abound (e.g. \u003ca href\u003d\"https://crbug.com/447742\"\u003ehttps://crbug.com/447742\u003c/a\u003e).  The reason is because \"negative\" Time values can represent a point-in-time before epoch (e.g, kernel boot time for TimeTicks).  These negative values can then increment over time and become zero at some point.  This then fools code into thinking a Time value is \"unset\" when it has actually been assigned/incremented to zero.\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003eInstead of \u003ccode\u003e0LL\u003c/code\u003e, which is dirt-smack in the middle of the range of possible values, a boundary value should represent the \"unset\" value: \u003ccode\u003ekint64min\u003c/code\u003e.  The default constructors for base::Time and base::TimeTicks should then initialize to \u003ccode\u003ekint64min\u003c/code\u003e as well.  We will have to be careful that this does not break any assumptions in client code.\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Zero-TimeDelta-Operations\" /\u003e\"Zero\" TimeDelta Operations\u003c/h2\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eCurrently, a lot of code does stuff like this:\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eif (last_foo_offset_ \u0026lt; base::TimeDelta())\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  last_foo_offset_ \u003d base::TimeDelta();\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003ccode\u003e...or...\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003ccode\u003eDCHECK_GT(duration, base::TimeDelta());\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003ccode\u003e...or...\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:10pt;line-height:1\"\u003e\u003ccode\u003eSetNetworkingDelay(base::TimeDelta());\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cbr /\u003e\u003cdiv\u003eThese lines of code are poor for readability.  Instead, the TimeDelta class should provide convenience methods for a global \"zero\" constant as well \"compare-to-zero\".  Then, the example above becomes:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eif (last_foo_offset_.is_negative())\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  last_foo_offset_ \u003d base::TimeDelta::Zero();\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e...or...\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eDCHECK(duration.is_positive());\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e...or...\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eSetNetworkingDelay(base::TimeDelta::Zero());\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cbr /\u003eAfter migrating code to use the new convenience methods, a PRESUBMIT check should be added to make sure future code changes don't regress the code base.  (Note: The no-arg base::TimeDelta constructor must remain public to allow for using this type in STL containers.)\u003cbr /\u003e\u003cbr /\u003e \u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/time-safety-and-readability"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8624588879735004767"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8624588879735004767"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8624588879735004767"}],"author":[{"name":{"$t":"Yuri Wiitala"},"email":{"$t":"miu@chromium.org"}}],"sites$pageName":{"$t":"time-safety-and-readability"},"sites$revision":{"$t":"7"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5237620656490223748"},"published":{"$t":"2015-01-22T01:34:10.186Z"},"updated":{"$t":"2015-01-22T01:34:10.213Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-22T01:34:10.186Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"twinkie_programming.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5237620656490223748"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/twinkie_programming.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5237620656490223748"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5237620656490223748"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5237620656490223748"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5237620656490223748"}],"author":[{"name":{"$t":"David Schneider"},"email":{"$t":"dnschneid@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"UCl7JmA4\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8230872963622938963"},"published":{"$t":"2013-10-27T01:44:50.970Z"},"updated":{"$t":"2015-01-16T21:46:38.514Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-16T21:46:37.454Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Run Mojo Shell"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-These-instructions-now-live-here:-https:-github.com-domokit-mojo-blob-master-README.md\" /\u003e\u003cfont size\u003d\"3\" style\u003d\"font-weight:normal\"\u003eThese instructions now live here: \u003ca href\u003d\"https://github.com/domokit/mojo/blob/master/README.md\" rel\u003d\"nofollow\"\u003ehttps://github.com/domokit/mojo/blob/master/README.md\u003c/a\u003e\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2433140667124192106"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/run-mojo-shell"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8230872963622938963"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8230872963622938963"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8230872963622938963"}],"author":[{"name":{"$t":"Adam Barth"},"email":{"$t":"abarth@chromium.org"}}],"sites$pageName":{"$t":"run-mojo-shell"},"sites$revision":{"$t":"49"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2063545744638270254"},"published":{"$t":"2015-01-13T20:16:02.215Z"},"updated":{"$t":"2015-01-16T19:09:37.022Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-16T19:08:56.247Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Crash with invalid handle"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-is-this-crash-about-\" /\u003eWhat is this crash about?\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-I-m-seeing-frequent-Chrome-crashes-and-the-stack-looks-like-this:\" /\u003eI'm seeing frequent Chrome crashes and the stack looks like this:\u003c/h3\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[debugger_win.cc:20 ]           base::debug::BreakDebugger()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[scoped_handle.cc:79 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::win::HandleTraits::CloseHandle()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[file_win.cc:120 ]              base::File::Close()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[file_stream_context.cc:184 ]   net::FileStream::Context::CloseFileImpl()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[bind_internal.h:1169 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::internal::Invoker\u0026lt;\u0026gt;::Run()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[sequenced_worker_pool.cc:760 ]\u003cspan style\u003d\"white-space:pre\"\u003e \u003c/span\u003ebase::SequencedWorkerPool::Inner::ThreadLoop()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[sequenced_worker_pool.cc:508 ]\u003cspan style\u003d\"white-space:pre\"\u003e \u003c/span\u003ebase::SequencedWorkerPool::Worker::Run()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[simple_thread.cc:60 ]          base::SimpleThread::ThreadMain()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[platform_thread_win.cc:78 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::`anonymous namespace'::ThreadFunc()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[kernel32.dll + 0x0004ee1b ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003eBaseThreadInitThunk\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[ntdll.dll + 0x000637ea ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003e__RtlUserThreadStart\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[ntdll.dll + 0x000637bd ]       _RtlUserThreadStart\u003c/font\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eor like this:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[debugger_win.cc:20 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::debug::BreakDebugger()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[scoped_handle.cc:79 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::win::HandleTraits::CloseHandle()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[scoped_handle.h:52 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::win::GenericScopedHandle\u0026lt;\u0026gt;::~GenericScopedHandle\u0026lt;\u0026gt;()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[handle_watcher.cc:271 ]        mojo::common::WatcherThreadManager::StopWatching()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[handle_watcher.cc:434 ]        mojo::common::HandleWatcher::SecondaryThreadWatchingState::~SecondaryThreadWatchingState()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[chrome.dll + 0x00238a03 ]      mojo::common::HandleWatcher::SecondaryThreadWatchingState::`scalar deleting destructor'()\u003c/font\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe relevant part is the first three lines that show that something is being closed and there is an intentional crash because there is an error closing that handle.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThese stacks point to a form of corruption in the past, which is only detected when the invalid handle is being closed. Like most forms of corruption, it is not safe to continue execution at this point, but at the time of the crash there is not enough information to know when (and where) the corruption was introduced.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-I-am-seeing-Chrome-hangs-with-stacks-like-this-one:\" /\u003eI am seeing Chrome hangs with stacks like this one:\u003c/h3\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[ntdll.dll + 0x00040da8 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003eZwWaitForSingleObject\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[KERNELBASE.dll + 0x00001128 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003eWaitForSingleObjectEx\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[KERNELBASE.dll + 0x000010b3 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003eWaitForSingleObject\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[platform_thread_win.cc:222 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::PlatformThread::Join()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[thread.cc:135 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::Thread::Stop()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[..._process_sub_thread.cc:26 ]\u003cspan style\u003d\"white-space:pre\"\u003e \u003c/span\u003econtent::BrowserProcessSubThread::~BrowserProcessSubThread()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[chrome.dll + 0x0043dcb8 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003econtent::BrowserProcessSubThread::`scalar deleting destructor'()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[browser_main_loop.cc:829 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003econtent::BrowserMainLoop::ShutdownThreadsAndCleanUp()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[browser_main_runner.cc:146 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003econtent::BrowserMainRunnerImpl::Shutdown()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[browser_main.cc:28 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003econtent::BrowserMain()\u003c/font\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThis is another manifestation of the same underlying issue: once a handle is corrupt, using it can do anything. If the OS detects that the handle is invalid, the operation generally fails right away. However, if the handle now points to something else, operations may appear to work but do something generally unexpected. The code in this example is simply waiting on the wrong object, so most likely it will never be signaled.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-to-do-about-it\" /\u003eWhat to do about it\u003c/h2\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWe have better detection baked into the 32-bit builds of Dev and Canary builds of Chrome. In that case, the crash stack will hopefully morph into something that points to the code at fault.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-For-users:\" /\u003eFor users:\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eConsider installing a \u003ca href\u003d\"https://www.google.com/chrome/browser/canary.html?platform\u003dwin\"\u003eCanary\u003c/a\u003e or \u003ca href\u003d\"https://www.google.com/chrome/browser/index.html?extra\u003ddevchannel\u0026amp;platform\u003dwin\"\u003eDev\u003c/a\u003e Channel Build (Windows only. See \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/getting-involved/dev-channel\"\u003ethis\u003c/a\u003e for information about what a channel is and what to do before installing a new one).\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eSearch your system for malware, and try removing software that interacts directly with Chrome by injecting DLLs. In the past we have seen correlation between 3rd party software loaded into Chrome and problems with invalid handles. You can get a list of all DLLs loaded into the browser by navigating to about:conflicts (note that most likely there are no detected conflicts even if a DLL is causing trouble).\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-For-bug-triage:\" /\u003eFor bug triage:\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eClose bugs that are reported on the Stable or Beta builds, as there is very little to do. Feel free to point to this page.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eIf the report comes directly from the stability result of a given version (top x on the crash server), search for a similar report and merge (it may be closed as WontFix). Avoid merging into a user-reported bug (there is a similar report somewhere for something that is internal \u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe ScopedHandle verifier is far from perfect, so even with a 32-bit build canary build it is bound to generate dumps that follow the same pattern of dumps from Stable. Ignore those reports.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-For-developers:\" /\u003eFor developers:\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eA Canary build will generate a properly bucketed stack dump like this:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[scoped_handle.cc:145 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::win::OnHandleBeingClosed()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[close_handle_hook_win.cc:27 ]  `anonymous namespace'::CloseHandleHook()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[shared_memory_win.cc:75 ]      base::SharedMemory::~SharedMemory()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[resource_buffer.cc:42 ]        content::ResourceBuffer::~ResourceBuffer()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[ref_counted.h:192 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003ebase::RefCountedThreadSafe\u0026lt;\u0026gt;::DeleteInternal()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[async_resource_handler.cc:99 ]\u003cspan style\u003d\"white-space:pre\"\u003e \u003c/span\u003econtent::AsyncResourceHandler::~AsyncResourceHandler()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[chrome.dll + 0x003af3ae ]      content::AsyncResourceHandler::`scalar deleting destructor'()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[...ed_resource_handler.cc:19 ]\u003cspan style\u003d\"white-space:pre\"\u003e \u003c/span\u003econtent::LayeredResourceHandler::~LayeredResourceHandler()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[chrome.dll + 0x003aebc7 ]\u003cspan style\u003d\"white-space:pre\"\u003e  \u003c/span\u003econtent::BufferedResourceHandler::`scalar deleting destructor'()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[...ed_resource_handler.cc:19 ]\u003cspan style\u003d\"white-space:pre\"\u003e \u003c/span\u003econtent::LayeredResourceHandler::~LayeredResourceHandler()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[chrome.dll + 0x003ae5f8 ]      content::ThrottlingResourceHandler::`scalar deleting destructor'()\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[resource_loader.cc:104 ]       content::ResourceLoader::~ResourceLoader()\u003c/font\u003e\u003c/div\u003e\r\n\u003c/blockquote\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIt points to ~SharedMemory as the source of corruption. This means that said code is either double closing a handle somehow (most of the time it is far from obvious how that happens), or it is not really doing anything wrong but it is being blamed anyway. In any case, this code should not be doing manual handle management so it should be refactored to use ScopedHandle instead.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIf there is a bug, it most likely will go away with the refactor. If there was no bug, ScopedHandle verifier will stop blaming this code, and the overall reliability of the verifier will go up.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eSo the take away is... refactor the code to remove manual handle management. This also means to modify interfaces to remove passing raw handles around and instead pass a ScopedHandle (or something that encapsulates the handle  using a ScopedHandle internally). There's plenty of code to choose from!. See bugs \u003ca href\u003d\"http://crbug.com/322664\"\u003e322664\u003c/a\u003e, \u003ca href\u003d\"http://crbug.com/416721\"\u003e416721\u003c/a\u003e or \u003ca href\u003d\"http://crbug.com/417532\"\u003e417532\u003c/a\u003e for some examples.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eSearch the crash server for stacks containing OnHandleBeingClosed to get a summary of issues currently detected as problematic.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3346586720904756379"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/crash-reports/crash-with-invalid-handle"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2063545744638270254"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2063545744638270254"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2063545744638270254"}],"author":[{"name":{"$t":"Ricardo Vargas"},"email":{"$t":"rvargas@chromium.org"}}],"sites$pageName":{"$t":"crash-with-invalid-handle"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6514021724066353893"},"published":{"$t":"2015-01-13T19:53:42.280Z"},"updated":{"$t":"2015-01-14T23:03:35.468Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-14T23:03:34.262Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Mac Window Occlusion API Use"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eOn Mac, a NSWindow can check to see if it is visible to the user (that is, check to see if it is not covered by other windows, or on another desktop). This document discusses how this feature can be used to save power.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"5\"\u003e\u003cb\u003e\u003cu\u003eVisible and Hidden on RenderWidget and RenderWidgetHostView\u003c/u\u003e\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThere are two separate pieces of state that are currently conflated (they are always kept in lock-step), which need to be decoupled for this feature.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eRenderWidget::SetHidden\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis is in the renderer process. It is controlled through calling RenderWidgetHostImpl::WasHidden/WasShown, which sends a ViewMsg_WasHidden/Shown IPC down to the renderer. This will make the renderer process stop producing frames, and free up some resources. This state is entered when a tab is backgrounded.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis is the state that is queried by the Javascript Page Visibility API. See the example at http://ie.microsoft.com/TEStdrive/Performance/PageVisibility/Default.html\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOf note is that on Safari, unlike Chrome (for now), the Page Visibility API indicates that the page is hidden when it is occluded. We should match this behavior.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAlso of note is that when a page has a frame subscriber (for tab capture), the renderer must always be in the visible state, not the hidden state.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eRenderWidgetHostView::Show/Hide and RenderWidgetHostViewBase::WasShown/WasHidden\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThese functions control if the RenderWidgetHostViewCocoa (the NSView corresponding to the RenderWidgetHostViewMac) is actually visible on-screen. It is possible (and does happen) that there are multiple RenderWidgetHostViewCocoas attached to the same NSWindow, and which one is visible is controlled by this Show/Hide method.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIt is these functions that call RenderWidgetHostImpl::WasHidden/Shown, which, in turn, tells the renderer what is happening, keeping this state in lock-step with the RenderWidget.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThese functions are called by WebContentsImpl::WasShown/WasHidden.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eRelationship with Tab Capture\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen a WebContentsImpl starts capturing, the active capture will (sometimes, hopefully) prevent WebContents::WasHidden from being called.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis is done by the WebContents::should_normally_be_visible() flag, which all callers to \u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eWebContents::\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eWasHidden need to check (very brittle).\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThis is also accomplished by having WebContentsImpl::DecrementCapturerCount potentially call WasHidden when the last capturer goes away.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"5\"\u003e\u003cu\u003eProblems With This Situation for Occlusion\u003c/u\u003e\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen a Chrome window is occluded, we will want the RenderWidget in the renderer process to be told that it is hidden (this will cause it to drop its resources and to indicate this to Javascript), but we do not want the the NSView for the RenderWidgetHostView to be hidden (because we want it to be immediately visible when the window is un-covered).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis combination of state, where the RenderWidget is not visible, but the RenderWidgetHostView is visible, is not currently supported.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"5\"\u003e\u003cb\u003e\u003cu\u003eProposed Changes\u003c/u\u003e\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eWe should divorce the ideas of the RenderWidgetHostView being visible from the RenderWidget being visible. When doing tab capture, it is necessary that the RenderWidget be visible, but the RenderWidgetHostView should be capable of being hidden.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eAt present, the relevant interface between WebContentsImpl and RenderWidgetHostView is through WebContentsImpl calling RenderWidgetHostView::Show/Hide.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis interface can be changed in two ways.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eProposal A (not favored):\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSplit this interface into RenderWidgetHostView::CaptureWasStarted/Stopped and RenderWidgetHostView::Show/\u003cb\u003eShowOccluded\u003c/b\u003e/Hide.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFrom there, it will be up to the various RenderWidgetHostViews implementations to decide if they want to conflate these, and how it wants to separate them out.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eProposal B (favored):\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSplit this interface into RenderWidgetHostView::ShowWidget/HideWidget and RenderWidgetHostView::Show/Hide.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn this version, WebContentsImpl takes care of the logic to determine, based on the view state and the capture state, if the RenderWidget should be visible or hidden. The RenderWidgetHostView, meanwhile, can add optimizations to partially-deactivate the view if it knows that the RenderWidget has been hidden (and therefore won't be updating its content often). It's not clear if a ShowOccluded function is very useful here (occluded state can be inferred from the RenderWidget being hidden but the view being visible), but the possibility shouldn't be excluded.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont size\u003d\"4\"\u003eNew Configurations\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eFor situations where tab capture is enabled, but the tab being captured is backgrounded, the RenderWidget will be visible, but the RenderWidgetHostView will not be.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:13.3333330154419px\"\u003e\u003cspan style\u003d\"font-size:13.3333330154419px;background-color:transparent\"\u003eFor situations where the window is occluded, the RenderWidget will not be visible, but the RenderWidgetHostView will be.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/mac-occlusion"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6514021724066353893"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6514021724066353893"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6514021724066353893"}],"author":[{"name":{"$t":"ccameron chromium"},"email":{"$t":"ccameron@chromium.org"}}],"sites$pageName":{"$t":"mac-occlusion"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3377909064936459878"},"published":{"$t":"2015-01-09T23:23:40.830Z"},"updated":{"$t":"2015-01-09T23:23:40.873Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-09T23:23:40.830Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"810-10116-02_20150109_hdmi_SCH_0.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3377909064936459878"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/hoho/810-10116-02_20150109_hdmi_SCH_0.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3377909064936459878"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3377909064936459878"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3377909064936459878"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3377909064936459878"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1875056396993167573"},"published":{"$t":"2015-01-09T01:39:15.720Z"},"updated":{"$t":"2015-01-09T01:39:15.760Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-09T01:39:15.720Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"HoHo Block Diagram (1).png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1875056396993167573"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/hoho/HoHo%20Block%20Diagram%20(1).png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1875056396993167573"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1875056396993167573"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1875056396993167573"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1875056396993167573"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2415643134176243406"},"published":{"$t":"2015-01-08T01:33:03.298Z"},"updated":{"$t":"2015-01-08T01:33:03.335Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-08T01:33:03.298Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"DingDong Block Diagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2415643134176243406"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8602524482882798267"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/dingdong/DingDong%20Block%20Diagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2415643134176243406"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2415643134176243406"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2415643134176243406"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2415643134176243406"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6324724750366815833"},"published":{"$t":"2015-01-08T00:47:25.938Z"},"updated":{"$t":"2015-01-08T00:47:25.971Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2015-01-08T00:47:25.938Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"HoHo Block Diagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6324724750366815833"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6186844832924451598"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/hoho/HoHo%20Block%20Diagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6324724750366815833"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6324724750366815833"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6324724750366815833"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6324724750366815833"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1933119246987131205"},"published":{"$t":"2014-12-23T21:23:36.439Z"},"updated":{"$t":"2014-12-23T21:24:01.379Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-23T21:23:59.422Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"chrome.test APIs"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv dir\u003d\"ltr\" style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8000001907349px\"\u003eThe chrome.test extension API is defined in \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/extensions/common/api/test.json\u0026amp;q\u003dtest.json\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003esrc/extensions/common/api/test.json\u003c/a\u003e, that file also has some documentation for some of the methods it defines. The same code that injects all other extension APIs in the right context (\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/extensions/renderer/dispatcher.cc\u0026amp;l\u003d1089\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003eextensions::Dispatcher::UpdateBindingsForContext\u003c/a\u003e) also is responsible for injecting the chrome.test bindings (there is some special code there to not inject the chrome.test API unless the process has a --test-type command line flag). The \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/extensions/common/api/_api_features.json\u0026amp;l\u003d270\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003esrc/extensions/common/api/_api_features.json\u003c/a\u003e file determines in what contexts the chrome.test API (and other extension APIs as well) will be injected.\u003c/div\u003e\u003cdiv style\u003d\"outline:none;padding:10px 0px;width:22px;color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8000001907349px\" /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1447271005938918470"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/testing/chrome-test-apis"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1933119246987131205"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1933119246987131205"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1933119246987131205"}],"author":[{"name":{"$t":"Mark Foltz"},"email":{"$t":"mfoltz@chromium.org"}}],"sites$pageName":{"$t":"chrome-test-apis"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7062441389825691422"},"published":{"$t":"2014-12-18T23:08:22.015Z"},"updated":{"$t":"2014-12-18T23:08:22.075Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-18T23:08:22.015Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"media_router_ui_diagram.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7062441389825691422"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/media_router_ui_diagram.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7062441389825691422"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7062441389825691422"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7062441389825691422"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7062441389825691422"}],"author":[{"name":{"$t":"Jennifer Apacible"},"email":{"$t":"apacible@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7969682836574709861"},"published":{"$t":"2014-12-18T23:08:01.736Z"},"updated":{"$t":"2014-12-18T23:08:01.776Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-18T23:08:01.736Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"media_router_screen_selector.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7969682836574709861"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/media_router_screen_selector.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7969682836574709861"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7969682836574709861"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7969682836574709861"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7969682836574709861"}],"author":[{"name":{"$t":"Jennifer Apacible"},"email":{"$t":"apacible@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6380744929988126514"},"published":{"$t":"2014-12-18T22:56:23.175Z"},"updated":{"$t":"2014-12-18T22:56:23.223Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-18T22:56:23.175Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"media_router_universal_remote.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6380744929988126514"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/media_router_universal_remote.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6380744929988126514"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6380744929988126514"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6380744929988126514"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6380744929988126514"}],"author":[{"name":{"$t":"Jennifer Apacible"},"email":{"$t":"apacible@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6581216885482020212"},"published":{"$t":"2014-12-18T22:52:00.159Z"},"updated":{"$t":"2014-12-18T22:52:00.195Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-18T22:52:00.159Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"media_router_overflow.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6581216885482020212"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/media_router_overflow.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6581216885482020212"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6581216885482020212"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6581216885482020212"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6581216885482020212"}],"author":[{"name":{"$t":"Jennifer Apacible"},"email":{"$t":"apacible@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDUpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7471817765000004822"},"published":{"$t":"2009-07-07T17:45:59.462Z"},"updated":{"$t":"2014-12-18T20:26:13.927Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-18T20:26:12.567Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Software Updates: Courgette"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-Courgette-works\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eHow Courgette works\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Compiled-code\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eCompiled code\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-More-than-one-executable-less-than-an-executable\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eMore than one executable, less than an executable\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Source-Code\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eSource Code\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Summary\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eSummary\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-How-Courgette-works\" /\u003eHow Courgette works\u003c/h4\u003e\r\n\u003cp\u003eAs I described in \u003ci\u003e\u003ca href\u003d\"http://blog.chromium.org/2009/07/smaller-is-faster-and-safer-too.html\"\u003eSmaller is faster (and safer too)\u003c/a\u003e\u003c/i\u003e, we wrote a new differential compression algorithm for making Google Chrome updates significantly smaller.\u003c/p\u003e\r\n\u003cp\u003eWe want smaller updates because it \u003ci\u003enarrows the window of vulnerability\u003c/i\u003e.  If the update is a tenth of the size, we can push ten times as many per unit of bandwidth.  We have enough users that this means more users will be protected earlier.  A secondary benefit is that a smaller update will work better for users who don't have great connectivity.\u003c/p\u003e\r\n\u003cp\u003eRather than push put a whole new 10MB update, we send out a diff that takes the previous version of Google Chrome and generates the new version.  We tried several binary diff algorithms and have been using \u003ca href\u003d\"http://www.daemonology.net/bsdiff/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(85,26,139)\" target\u003d\"_blank\" title\u003d\"http://www.daemonology.net/bsdiff/\"\u003ebsdiff\u003c/a\u003e up until now.  We are big fans of bsdiff - it is small and worked better than anything else we tried.\u003c/p\u003e\r\n\u003cp\u003eBut bsdiff was still producing diffs that were bigger than we felt were necessary.  So we wrote a new diff algorithm that knows more about the kind of data we are pushing - large files containing compiled executables.  Here are the sizes in bytes for the recent 190.1-\u0026gt;190.4 update on the developer channel:\u003c/p\u003e\r\n\u003ctable border\u003d\"1\" bordercolor\u003d\"#000000\" cellpadding\u003d\"3\" cellspacing\u003d\"0\" style\u003d\"font-size:1em;line-height:inherit;border-collapse:collapse\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd\u003eFull update\u003c/td\u003e\r\n\u003ctd\u003e10,385,920\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd\u003ebsdiff update\u003c/td\u003e\r\n\u003ctd\u003e    704,512\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd\u003eCourgette update\u003c/td\u003e\r\n\u003ctd\u003e      78,848\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003cp\u003eThe small size in combination with Google Chrome's silent update means we can update as often as necessary to keep users safe.\u003c/p\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Compiled-code\" /\u003eCompiled code\u003c/h4\u003e\r\n\u003cp\u003eThe problem with compiled applications is that even a small source code change causes a disproportional number of byte level changes.  When you add a few lines of code, for example, a range check to prevent a buffer overrun, all the subsequent code gets moved to make room for the new instructions.  The compiled code is full of internal references where some instruction or datum contains the address (or offset) of another instruction or datum.  It only takes a few source changes before almost all of these internal pointers have a different value, and there are a lot of them - roughly half a million in a program the size of chrome.dll.\u003c/p\u003e\r\n\u003cp\u003eThe source code does not have this problem because all the entities in the source are \u003ci\u003esymbolic\u003c/i\u003e. Functions don't get committed to a specific address until very late in the compilation process, during assembly or linking.  If we could step backwards a little and make the internal pointers symbolic again, could we get smaller updates?\u003c/p\u003e\r\n\u003cp\u003eCourgette uses a primitive disassembler to find the internal pointers.  The disassembler splits the program into three parts: a list of the internal pointer's target addresses, all the other bytes, and an 'instruction' sequence that determines how the plain bytes and the pointers need to be interleaved and adjusted to get back the original input.  We call this an 'assembly language' because we can run an 'assembler' to process the instructions and emit a sequence of bytes to recover the original file.\u003c/p\u003e\r\n\u003cp\u003eThe non-pointer part is about 80% of the size of the original program, and because it does not have any pointers mixed in, it tends to be well behaved, having a diff size that is in line with the changes in the source code.  Simply converting the program into the assembly language form makes the diff produced by bsdiff about 30% smaller.\u003c/p\u003e\r\n\u003cp\u003eWe bring the pointers under control by introducing 'labels' for the addresses.  The addresses are stored in an array and the list of pointers is replaced by a list of array indexes.  The array is a primitive 'symbol table', where the names of the symbols, or 'labels' are the integer indexes into the array.  What we get from the symbol table is a degree of freedom in how we express the program.  We can move the addresses around in the array provided we make the corresponding changes to the list of indexes.\u003c/p\u003e\r\n\u003cp\u003eHow do we use this to generate a better diff?  With bsdiff we would compute the new file, 'update' from the 'original' like this:\u003c/p\u003e\r\n\u003cdiv\u003e    server:\u003cbr /\u003e\r\n        diff \u003d bsdiff(original, update)\u003cbr /\u003e\r\n        transmit diff\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e    client:\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e        receive diff\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e        update \u003d bspatch(original, diff)\u003c/div\u003e\r\n\u003cp\u003e(The server would pre-compute diff so that it could be transmitted immediately)\u003c/p\u003e\r\n\u003cp\u003eCourgette transforms the program into the primitive assembly language and does the diffing at the assembly level:\u003c/p\u003e\r\n\r\n\u003cdiv\u003e    server:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e        asm_old \u003d disassemble(original)\u003c/div\u003e\r\n\u003cdiv\u003e        asm_new \u003d disassemble(update)\u003c/div\u003e\r\n\u003cdiv\u003e        asm_new_adjusted \u003d adjust(asm_new, asm_old)\u003c/div\u003e\r\n\u003cdiv\u003e        asm_diff \u003d bsdiff(asm_old, asm_new_adjusted)\u003c/div\u003e\r\n\u003cdiv\u003e        transmit asm_diff\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e    client:\u003c/div\u003e\r\n\u003cdiv\u003e        receive asm_diff\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e        asm_old \u003d disassemble(original)\u003c/div\u003e\r\n\u003cdiv\u003e        asm_new_adjusted \u003d bspatch(asm_old, asm_diff)\u003c/div\u003e\r\n\u003cdiv\u003e        update \u003d assemble(asm_new_adjusted)\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eThe special sauce is the adjust step.  Courgette moves the addresses within the asm_new symbol table to minimize the size of asm_diff.  Addresses in the two symbol tables are matched on their statistical properties which ensures the index lists have many long common substrings.  The matching does not use any heuristics based on the surrounding code or debugging information to align the addresses.\u003c/p\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-More-than-one-executable-less-than-an-executable\" /\u003eMore than one executable, less than an executable\u003c/h4\u003e\r\n\u003cp\u003eFor the above to work, 'assemble' and 'disassemble' have to be strict inverses, and 'original' and 'update' have to be single well-formed executable files.  It is much more useful if 'original' and 'update' can contain several executables as well as a lot of non-compiled files like JavaScript and PNG images.  For Google Chrome, the 'original' and 'update' are an archive file containing all the files needed to install and run the browser.\u003c/p\u003e\r\n\u003cp\u003eWe can think of a differential update as a prediction followed by a correction, a kind of guessing game.  In its simplest form (just bsdiff / bspatch), the client has only a dumb guess, 'original', so the server sends a binary diff to correct 'original' to the desired answer, 'update'.  Now what if the server could pass a hint that could be used to generate a better guess, but we are not sure the guess will be useful?  We could insure against losing information by using the original and the guess together as the basis for the diff:\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e    server:\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e        hint \u003d make_hint(original, update)\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e        guess \u003d make_guess(original, hint)\u003c/div\u003e\r\n\u003cdiv\u003e        diff \u003d bsdiff(concat(original, guess), update)\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e        transmit hint, diff\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e    client\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e        receive hint, diff\u003c/div\u003e\r\n\u003cdiv\u003e        guess \u003d make_guess(original, hint)\u003c/div\u003e\r\n\u003cdiv\u003e        update \u003d bspatch(concat(original, guess), diff)\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eThis system has some interesting properties.  If the guess is the empty string, then we have the same diff as with plain bsdiff.  If the guess is perfect, the diff will be tiny, simply a directive to copy the guess.\u003c/p\u003e\r\n\u003cp\u003eBetween the extremes, the guess could be a perfect subset of 'update'.  Then bsdiff will construct a diff that mostly takes material from the perfect prediction and the original to construct the update.  This is how Courgette deals with inputs like tar files containing both executable files and other files.  The hint is the location of the embedded executables together with the asm_diff for each one.\u003c/p\u003e\r\n\u003cp\u003eOnce we have this prediction / correction scheme in place we can use it to reduce the amount of work that the client needs to do.  Executables often have large regions that do not contain internal pointers, like the resource section which usually contains string tables and various visual elements like icons and bitmaps.  The disassembler generates an assembly language program which pretty much says 'here is a big chunk of constant data', where the data is identical to the original file.  bsdiff then generates a diff for the constant data.  We can get substantially the same effect by omitting the pointer-free regions from the disassembly and letting the final diff do the work.\u003c/p\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Source-Code\" /\u003eSource Code\u003c/h4\u003e\r\n\u003cp\u003eEveryone loves source, so you can find it here:\u003cbr /\u003e\r\n\u003ca href\u003d\"https://chromium.googlesource.com/chromium/src/courgette/+/master\"\u003ehttps://chromium.googlesource.com/chromium/src/courgette/+/master\u003c/a\u003e\u003c/p\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h4\u003e\r\n\u003cp\u003eCourgette transforms the input into an alternate form where binary diffing is more effective, does the differential compression in the transformed space, and inverts the transform to get the patched output in the original format.  With careful choice of the alternate format we can get substantially smaller updates.\u003c/p\u003e\r\n\u003cp\u003eWe are writing a more detailed paper on Courgette and will post an update when it is ready.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/software-updates-courgette"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7471817765000004822"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7471817765000004822"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7471817765000004822"}],"author":[{}],"sites$pageName":{"$t":"software-updates-courgette"},"sites$revision":{"$t":"9"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1960944805803152240"},"published":{"$t":"2014-10-21T21:54:27.549Z"},"updated":{"$t":"2014-12-16T19:25:59.669Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-16T19:25:58.245Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Handling Mac Overscroll On the Compositor Thread"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eDesign document is at\u003cdiv\u003ehttps://docs.google.com/a/chromium.org/document/d/1ePfdAkOKh7DMc7UBOyyXrkmf_25e-d8zTJktAGHtcTw/edit\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9026127630943746559"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/chromium-graphics/mac-impl-events"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1960944805803152240"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1960944805803152240"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1960944805803152240"}],"author":[{"name":{"$t":"ccameron chromium"},"email":{"$t":"ccameron@chromium.org"}}],"sites$pageName":{"$t":"mac-impl-events"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/335783694249540746"},"published":{"$t":"2014-12-16T18:10:26.972Z"},"updated":{"$t":"2014-12-16T18:10:27.012Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-16T18:10:26.972Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Chrome Media Router - Chrome architecture (1).png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/335783694249540746"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/Chrome%20Media%20Router%20-%20Chrome%20architecture%20(1).png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/335783694249540746"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/335783694249540746"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/335783694249540746"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/335783694249540746"}],"author":[{"name":{"$t":"In-Ming Cheng"},"email":{"$t":"imcheng@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3987566346952948349"},"published":{"$t":"2014-12-16T02:19:57.166Z"},"updated":{"$t":"2014-12-16T02:19:57.196Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-16T02:19:57.166Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Chrome Media Router - Chrome architecture.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3987566346952948349"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7510377848164588562"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/media-router/Chrome%20Media%20Router%20-%20Chrome%20architecture.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3987566346952948349"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3987566346952948349"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3987566346952948349"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3987566346952948349"}],"author":[{"name":{"$t":"In-Ming Cheng"},"email":{"$t":"imcheng@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4981696505002534843"},"published":{"$t":"2014-12-13T02:28:12.133Z"},"updated":{"$t":"2014-12-13T02:28:12.177Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-13T02:28:12.133Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"boot_design_diagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4981696505002534843"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9108204357917639229"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/boot-design/boot_design_diagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4981696505002534843"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4981696505002534843"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4981696505002534843"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4981696505002534843"}],"author":[{"name":{"$t":"Richard Barnette"},"email":{"$t":"jrbarnette@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"XSl7JmA5\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1111123889964029428"},"published":{"$t":"2008-11-04T01:22:10.269Z"},"updated":{"$t":"2014-12-11T18:35:51.150Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-11T18:35:50.088Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Performance Test Plots - to track performance regressions"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"border-collapse:separate\"\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;margin-top:0px;margin-bottom:0px\"\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cfont size\u003d\"4\"\u003eWarning: this page is stale. Performance test results are now displayed at \u003ca href\u003d\"https://chromeperf.appspot.com/\"\u003echromeperf.appspot.com\u003c/a\u003e.\u003c/font\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana;margin-top:0px;margin-bottom:0px\"\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cfont size\u003d\"4\"\u003eSee:\u003c/font\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://dev.chromium.org/chromium-os/testing/perf-data\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"4\"\u003eUser Guide: Chrome OS Performance Tests and the Chrome Performance Dashboard\u003c/font\u003e\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003cfont color\u003d\"#ff0000\" face\u003d\"arial, sans-serif\" size\u003d\"4\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/testing/adding-performance-tests\"\u003eAdding Performance Tests\u003c/a\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"4\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:43c7dde961b4942e\" class\u003d\"disabled\"\u003eSending Data to the Performance Dashboard\u003c/a\u003e\u003c/font\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003chr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cfont face\u003d\"Verdana\"\u003eChromium's buildbot runs a battery of performance tests on each build it produces.  These performance test results are collected and viewable on the web to help Chromium developers study how the project's builds perform over time.  By adding new tests, tuning existing tests, and configuring monitors to alert developers to unexpected conditions (such as regressions or speedups), the Chromium project continually improves its overall code quality.  This document explains how that performance testing system functions and how changes can be introduced.\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Verdana;margin-right:auto\"\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Gathering-performance-results\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eGathering performance results\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-A-sample-performance-plot\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eA sample performance plot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Adding-a-new-performance-plot\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eAdding a new performance plot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Monitoring-performance-for-regressions\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eMonitoring performance for regressions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Format-of-expectations-file\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eFormat of expectations file\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Perf-expectations-example\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003ePerf expectations example\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Updating-performance-expectations-selecting-acceptable-results-...\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003eUpdating performance expectations, selecting acceptable results, ...\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Gathering-performance-results\" /\u003eGathering performance results\u003c/h3\u003e\u003cspan style\u003d\"border-collapse:separate\"\u003e\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003eEach performance test is run by buildbot by executing that test's harness.  The harness sets up the initial conditions for the test, runs the test (maybe repeatedly), and reports results on the program's standard output.  You can build and run a test harness on your system -- these are the same programs the buildbot runs to measure performance.  Note that your performance results could vary considerably from what the Chromium project's test systems report.\u003c/div\u003e\u003ch3 style\u003d\"font-family:Verdana;font-size:13px\"\u003e\u003ca name\u003d\"TOC-A-sample-performance-plot\" /\u003eA sample performance plot\u003c/h3\u003e\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003eTest runs can be simple -- \"test the amount of time it takes to switch between two tabs\" -- or complicated -- \"test warm/cold startup performance with/without themes.\"  Most of the tests run by the buildbot are pretty straightforward, but the performance test output can be hard to use at first. Let's look at the most complicated kind of performance test, a page-cycler test, as an example. The page-cycler tests take a set of URLs that have been saved to local files to eliminate the network as a source of performance noise, and load them several times each, tracking various data. Find a \"Perf\" builder, scroll down to any page_cycler step, and click the \"results\" link.  You'll see a plot like this one:\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cdiv style\u003d\"display:block;margin-right:auto;margin-left:auto;text-align:center\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/performance-test-plots/page_cycler_plot.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1243880536868/developers/testing/chromium-build-infrastructure/performance-test-plots/page_cycler_plot.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003eThe boxes along the top list the different graphs available, one for each kind of data that was collected by the page_cycler test. Click on one to see that information plotted. Here's what all the pieces of the names mean:\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003ctable border\u003d\"0\" cellpadding\u003d\"3\" cellspacing\u003d\"0\" style\u003d\"border:1px dotted gray;font-size:1em;line-height:inherit\"\u003e\u003ctbody\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003etimes\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003etime in milliseconds to load each page once\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003e_b\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003ea data point collected from the browser process\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003e_r\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003ea data point collected from the renderer process\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003evm_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003evirtual memory used\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003ews_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003eworking-set memory used\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003e_peak_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003epeak memory usage during the entire test\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003e_final_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003ememory usage when the test ended\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003e_op_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003eI/O operations\u003cbr /\u003e\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003e_byte_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003eI/O bytes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003eread_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003eI/O ops or bytes read\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003ewrite_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003eI/O ops or bytes written\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003eother_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003eany other I/O bytes or ops\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr style\u003d\"text-align:left\"\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:126px;height:16px\"\u003etotal_\u003c/td\u003e\r\n\u003ctd style\u003d\"border:1px dotted gray;width:651px;height:16px\"\u003esum of read, write, and other I/O\u003cbr /\u003e\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\u003c/table\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\r\n\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003eSo for example, \"vm_final_b\" is the final VM usage of the browser process.\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003eDepending on the graph you're looking at, there will be one or more colored lines, or \"traces\". Generally one of these is the main data point for the build being tested (\"t\" for times, for instance) and one is data taken from a reference build so we can discount temporary glitches on the machine (\"t_ref\" for reference times). Other traces might be shown, too, and described in the legend below the plot.\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Verdana\"\u003eIf you click your mouse on the plot, one build will be highlighted by a grey vertical line, and the svn log for the build you've selected will be shown in a frame below the plot. Below the legend is the revision number and first data point (using the order on the legend) for that revision. It's followed by the data value for the spot your mouse is hovering over, so you can quickly compare two points.  If you shift-click on the plot, you'll place a horizontal marker, and the offset between that marker and the mouse is shown in the lower right.\u003c/font\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cdiv style\u003d\"font-family:Verdana;margin-top:0px;margin-bottom:0px\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Adding-a-new-performance-plot\" /\u003eAdding a new performance plot\u003c/h3\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana;margin-top:0px;margin-bottom:0px\"\u003eWhen\r\na Chromium developer wants to measure a new aspect of Chromium's\r\nperformance, the developer either modifies an already-in-place harness\r\nto provide additional data or creates a new harness to produce this\r\ndata.  When a new harness is added, the Chromium buildbot's\r\nconfiguration is updated to run it and told where to gather its\r\nperformance test results.  Modifying a harness to add more data may not\r\nrequire any buildbot configuration changes.\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Verdana\"\u003eTests in Chromium typically use one of the met\u003c/font\u003e\u003cfont face\u003d\"verdana, sans-serif\"\u003ehods in \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/chrome/test/perf/perf_test.h?view\u003dmarkup\"\u003echrome/test/perf/perf_test.h\u003c/a\u003e to print \u003c/font\u003e\u003cfont face\u003d\"Verdana\"\u003etheir results in the standard format expected by the post-processing scripts.\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3 style\u003d\"font-family:Verdana;font-size:13px\"\u003e\u003ca name\u003d\"TOC-Monitoring-performance-for-regressions\" /\u003eMonitoring performance for regressions\u003c/h3\u003e\u003cdiv\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"border-collapse:separate\"\u003e\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003eOnce\r\nthe Chromium buildbot runs all of a build's tests, it gathers the results on the perf dashboard and reports whether the test met, exceeded, or missed its expectations.  \u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003eThe Chromium buildbot follows this algorithm to determine what to report after gathering results:\u003cbr /\u003e\r\n\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:rgb(255,255,255)\"\u003eIf the current test crashes or times out:\u003cbr /\u003e-\u0026gt; \u003c/span\u003e\u003cspan style\u003d\"background-color:rgb(255,0,0)\"\u003eFAILURE\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/li\u003e\u003cli\u003eIf the current report being scanned doesn't match any trace instances (see \"Format of expectations file\" below) the buildbot is monitoring:\u003cbr /\u003e-\u0026gt; \u003cspan style\u003d\"background-color:rgb(0,255,0)\"\u003eSUCCESS\u003c/span\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/li\u003e\u003cli\u003eIf any monitored trace instance regressed:\u003cbr /\u003e-\u0026gt; \u003cspan style\u003d\"background-color:rgb(255,0,0)\"\u003eFAILURE\u003c/span\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/li\u003e\u003cli\u003eIf any monitored trace instance was faster than expected:\u003cbr /\u003e-\u0026gt; \u003cspan style\u003d\"background-color:rgb(255,153,0)\"\u003eWARNING\u003c/span\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-left:40px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/li\u003e\u003cli\u003eIf all monitored trace instances were within expectations:\u003cbr /\u003e-\u0026gt; \u003cspan style\u003d\"background-color:rgb(0,255,0)\"\u003eSUCCESS\u003c/span\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\r\nIn a non-success result, the build's details are updated to include a description of which graph+trace regressed or got faster.\u003c/span\u003e\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Format-of-expectations-file\" /\u003eFormat of expectations file\u003c/h4\u003ePerf regression monitoring is controlled via \u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/tools/perf_expectations/perf_expectations.json?view\u003dmarkup\"\u003esrc/tools/perf_expectations/perf_expectations.json\u003c/a\u003e.  This is a JSON file with the following format:\u003c/span\u003e\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e{\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003cbr /\u003e  \"PERFID/TEST/GRAPH/TRACE\": {\"reva\": REVA, \"revb\": REVB, \"improve\": IMPROVE, \"regress\": REGRESS},\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003c/font\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \"PERFID/TEST/GRAPH/TRACE\": {\"reva\": REVA, \"revb\": REVB, \"improve\": IMPROVE, \"regress\": REGRESS},\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Verdana;font-size:13px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \"PERFID/TEST/GRAPH/TRACE\": {\"reva\": REVA, \"revb\": REVB, \"improve\": IMPROVE, \"regress\": REGRESS},\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  ...\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e,\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \"load\": true\u003c/span\u003e\u003cbr style\u003d\"font-family:courier new,monospace\" /\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e}\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\u003cbr style\u003d\"font-family:verdana,sans-serif\" /\u003e\u003ctable border\u003d\"1\" bordercolor\u003d\"#888888\" cellspacing\u003d\"0\" style\u003d\"border-color:rgb(136,136,136);border-width:1px;border-collapse:collapse\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"width:54px;height:16px\"\u003e\u003cb\u003eName\u003c/b\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003e\u003cb\u003eType\u003cbr /\u003e\u003c/b\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003e\u003cb\u003eDescription \u003cbr /\u003e\u003c/b\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"text-align:left;width:54px;height:16px\"\u003ePERFID\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003estring\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003eSystem perf name (ie. xp-release-dual-core -- see factory/chromium_commands.py).\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:54px;height:16px\"\u003eTEST\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003estring\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003eTest name (ie. moz, startup -- see factory/chromium_commands.py).\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:54px;height:16px\"\u003eGRAPH\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003estring\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003eGraph name (ie. times, warm).\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:54px;height:16px\"\u003eTRACE\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003estring\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003eTrace name on the selected graph (ie. t, vm_rss_f_r). \u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eREVA\u003c/td\u003e\u003ctd\u003einteger\u003c/td\u003e\u003ctd\u003eStart (inclusive) of expected range (see make_expectations.py).\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eREVB\u003c/td\u003e\u003ctd\u003einteger\u003c/td\u003e\u003ctd\u003eEnd (inclusive) of expected range (see make_expectations.py).\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:54px;height:16px\"\u003eIMPROVE\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003einteger\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003eThe best result of the current trace less the ref trace.  In times tests, this is the lower value; in scores tests, the higher value.\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd style\u003d\"width:54px;height:16px\"\u003eREGRESS\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:55px;height:16px\"\u003einteger\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"width:630px;height:16px\"\u003eThe worst allowed result of the current trace less the ref trace.  In times tests, this is the higher value; in scores tests, the lower value.\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003eNotes:\u003cbr /\u003e\u003cul\u003e\u003cli\u003eSetting \"load\" to \"true\" enables performance regression monitoring.\u003cbr /\u003e\u003c/li\u003e\u003cli\u003eStrings must be quoted with \" (not ').\u003c/li\u003e\u003cli\u003eComments are not allowed in JSON.\u003cbr /\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Perf-expectations-example\" /\u003ePerf expectations example\u003c/h4\u003eTake the following perf_expectations.json file as an example:\u003cbr /\u003e\u003cpre\u003e{\"xp-release-dual-core/morejs/times/t\": {\"improve\": 50, \"regress\": 110},\u003cbr /\u003e \"xp-release-dual-core/startup/warm/t\": {\"improve\": -65, \"regress\": 25},\u003cbr /\u003e \"load\": true\u003cbr /\u003e}\u003cbr /\u003e\u003c/pre\u003eThis declares 2 trace instances that should be monitored for regressions, both on Chromium's XP perf test system.  The first -- xp-release-dual-core/morejs/times/t -- monitors results of the morejs page cycler's page load time.  It alerts when the page load time for the current build less the reference build is greater than 110ms.\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana;font-size:13px;margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003eThe second -- xp-release-dual-core/startup/warm/t -- monitors results of the warm startup test and alerts when the difference between the current build and reference build is greater than 25ms.\u003cbr /\u003e\u003cbr /\u003eFor each of these traces, warnings (not failures) are generated when speed ups occur.  A speed up occurs when a given result is better than the expected improve value.\u003c/div\u003e\u003ch4 style\u003d\"font-family:Verdana;font-size:13px\"\u003e\u003ca name\u003d\"TOC-Updating-performance-expectations-selecting-acceptable-results-...\" /\u003e\u003cb\u003eUpdating performance expectations, selecting acceptable results, ...\u003c/b\u003e\u003c/h4\u003eSee the \u003ca href\u003d\"http://dev.chromium.org/developers/tree-sheriffs/perf-sheriffs\" target\u003d\"_blank\"\u003ePerf Sheriffing\u003c/a\u003e page for more details about updating perf expectations, selecting acceptable results, etc.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6221461143622794976"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/performance-test-plots"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1111123889964029428"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1111123889964029428"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1111123889964029428"}],"author":[{"name":{"$t":"Pam Greene"},"email":{"$t":"pam@chromium.org"}}],"sites$pageName":{"$t":"performance-test-plots"},"sites$revision":{"$t":"54"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8913230392167253636"},"published":{"$t":"2009-10-20T20:14:59.121Z"},"updated":{"$t":"2014-12-10T19:34:04.581Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-10T19:34:04.580Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"X-Subresources: python server experiment"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"color:rgb(68,68,68);line-height:20px\"\u003e\u003ch3 align\u003d\"left\" style\u003d\"font-size:1.8em;font-weight:bold;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-left:10px;padding-right:10px;color:rgb(68,68,68);background-image:initial;background-color:transparent;background-position:initial initial;background-repeat:initial initial\"\u003e\u003ca name\u003d\"TOC-Experiment-1\" /\u003e\u003cspan dir\u003d\"ltr\"\u003eExperiment #1\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cspan dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan dir\u003d\"ltr\"\u003e   Andrew Oates \u0026lt;aoates@google.com\u0026gt;\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"background-color:transparent;min-height:150px;padding-bottom:5px\"\u003e\u003cdiv\u003e\u003ctable cellspacing\u003d\"0\" style\u003d\"width:1545px;table-layout:fixed;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"vertical-align:top;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Purpose-Description\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003ePurpose/Description\u003c/h1\u003eThe purpose of this experiment was to determine if significant gains could be had from adding the X-subresource headers to pages. If that was the case, further experimentation would be done.\u003cp\u003eSpecifically, I tested the effect of the prefetching on a page with several external Javascript resources, which would need to be loaded and run serially by the browser.\u003c/p\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Setup\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eSetup\u003c/h1\u003eThe experiment consisted of loading a single test page from a server, and timing the page load times under various conditions. There were three components: the server, the test files, and the client.\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Server\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eServer\u003c/h3\u003eThe server was a small HTTP server written in Python designed to serve static content and optionally scan the pages for tags and generate X-subresource for any external resources referenced in the document. It can also add an artificial latency to simulate adverse network conditions --- in this case, it simply waits a certain amount of time after receiving a GET request before sending back the response.\u003cp\u003eTODO(aoates): publish the modified python server.\u003c/p\u003e\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Client\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eClient\u003c/h3\u003eThe client was a standard build of Firefox 3.0.10 with a custom extension installed.\u003cp\u003eThe extension listens for incoming requests, grabs any X-subresource headers and initiates prefetch requests for all the referenced resources.\u003c/p\u003e\u003cp\u003eTODO(aoates): publish the firefox extension.\u003c/p\u003e\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Test-Pages\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eTest Pages\u003c/h3\u003eThe test pages consist of two variations on one page. In each case, the page loads and executes 10 external Javascript files, and collects timing information on how long the page load as well as each external JS load takes. The individual Javascript files print out a message to the page, and stall for a small amount of time (around 100ms).\u003cp\u003eIn the first variation, \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003etest5.html\u003c/code\u003e, the external Javascript files are hosted locally, alongside the page. They are therefore served by the Python server, which cannot handle multiple parallel connections. In the second variation, \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003etest5_corp.html\u003c/code\u003e, the Javascript files are hosted on a server which can handle parallel connections.\u003c/p\u003e\u003cp\u003eTODO(aoates): publish the actual web pages.\u003c/p\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Experimental-Groups\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eExperimental Groups\u003c/h1\u003eThere were four experimental groups, testing two variables:\u003cul\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003ePresence of X-subresource headers in test page headers, and\u003c/li\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003eLocation of external resources; either locally, served by the small Python HTTP server, or on remotely, on \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003ewww.corp.google.com\u003c/code\u003e and served by Apache.\u003c/li\u003e\u003c/ul\u003eIn each case, the test page itself was served locally by the Python webserver (which generated the headers). The server was run with the following command:\u003cp\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e./xsubserver.py --latency 300 [--no-xsubresource]\u003c/code\u003ewith the last parameter varying. This introduced a \"latency\" of 300ms to all content served by the Python web server; the server waited 300ms after receiving the request to send back the response. The number 300 was chosen to approximate the latency of downloading one of the javascript files from a typical server.\u003c/p\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Trials-and-Results\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eTrials and Results\u003c/h1\u003eEach group was run several times, and a representative set of results is presented in the table below. For each group, an overall page load time is presented, as is the load time of each Javascript \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003escript\u003c/code\u003e element (the time taken to load and execute the Javascript file).\u003ctable style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px\"\u003e\u003ccaption style\u003d\"color:rgb(107,93,64);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:dotted;border-right-style:dotted;border-bottom-style:dotted;border-left-style:dotted;border-top-color:rgb(204,204,204);border-right-color:rgb(204,204,204);border-bottom-color:rgb(204,204,204);border-left-color:rgb(204,204,204)\" /\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"vertical-align:top\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"vertical-align:top\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"vertical-align:top\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"vertical-align:top\"\u003e\u003ci\u003eResults of Experiment #1\u003c/i\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003ctbody\u003e\u003ctr\u003e\u003cth colspan\u003d\"2\" rowspan\u003d\"2\" style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003e\u003cbr /\u003e\u003c/th\u003e\u003cth colspan\u003d\"2\" style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003eExternal Resource Server\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003exsubserver.py\u003c/code\u003e (local)\u003c/th\u003e\u003cth style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003eApache/2.0.55 (remote)\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth rowspan\u003d\"2\" style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003eX-subresource\u003cbr /\u003eHeaders\u003c/th\u003e\u003cth style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003eYes\u003c/th\u003e\u003ctd style\u003d\"vertical-align:top\"\u003ePage Load: \u003ci\u003e3065 ms\u003c/i\u003e\u003cbr /\u003eJS #1 Load: 306 ms\u003cbr /\u003eJS #2 Load: 301 ms\u003cbr /\u003eJS #3 Load: 309 ms\u003cbr /\u003eJS #4 Load: 306 ms\u003cbr /\u003eJS #5 Load: 301 ms\u003cbr /\u003eJS #6 Load: 312 ms\u003cbr /\u003eJS #7 Load: 299 ms\u003cbr /\u003eJS #8 Load: 303 ms\u003cbr /\u003eJS #9 Load: 296 ms\u003cbr /\u003eJS #10 Load: 317 ms\u003c/td\u003e\u003ctd style\u003d\"vertical-align:top\"\u003ePage Load: \u003ci\u003e1366 ms\u003c/i\u003e\u003cbr /\u003eJS #1 Load: 379 ms\u003cbr /\u003eJS #2 Load: 108 ms\u003cbr /\u003eJS #3 Load: 116 ms\u003cbr /\u003eJS #4 Load: 106 ms\u003cbr /\u003eJS #5 Load: 107 ms\u003cbr /\u003eJS #6 Load: 106 ms\u003cbr /\u003eJS #7 Load: 107 ms\u003cbr /\u003eJS #8 Load: 107 ms\u003cbr /\u003eJS #9 Load: 107 ms\u003cbr /\u003eJS #10 Load: 106 ms\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003cth style\u003d\"text-align:left;color:rgb(68,68,68);font-weight:bold;vertical-align:top;background-image:initial;background-color:transparent;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);background-position:initial initial;background-repeat:initial initial\"\u003eNo\u003c/th\u003e\u003ctd style\u003d\"vertical-align:top\"\u003ePage Load: \u003ci\u003e4178 ms\u003c/i\u003e\u003cbr /\u003eJS #1 Load: 422 ms\u003cbr /\u003eJS #2 Load: 415 ms\u003cbr /\u003eJS #3 Load: 411 ms\u003cbr /\u003eJS #4 Load: 415 ms\u003cbr /\u003eJS #5 Load: 415 ms\u003cbr /\u003eJS #6 Load: 415 ms\u003cbr /\u003eJS #7 Load: 414 ms\u003cbr /\u003eJS #8 Load: 417 ms\u003cbr /\u003eJS #9 Load: 422 ms\u003cbr /\u003eJS #10 Load: 416 ms\u003c/td\u003e\u003ctd style\u003d\"vertical-align:top\"\u003ePage Load: \u003ci\u003e3777 ms\u003c/i\u003e\u003cbr /\u003eJS #1 Load: 487 ms\u003cbr /\u003eJS #2 Load: 353 ms\u003cbr /\u003eJS #3 Load: 342 ms\u003cbr /\u003eJS #4 Load: 342 ms\u003cbr /\u003eJS #5 Load: 352 ms\u003cbr /\u003eJS #6 Load: 356 ms\u003cbr /\u003eJS #7 Load: 352 ms\u003cbr /\u003eJS #8 Load: 347 ms\u003cbr /\u003eJS #9 Load: 484 ms\u003cbr /\u003eJS #10 Load: 351 ms\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Discussion\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eDiscussion\u003c/h1\u003eLet's examine each set of results.\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Python-local-without-prefetching\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003ePython/local without prefetching\u003c/h3\u003eIn this trial, there was an overall page load time (from execution of the first script tag to sending the body's \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003eonLoad\u003c/code\u003e event) of 4178 ms, with each individual javascript element taking a little over 400 ms to load and execute. This is exactly as expected --- with a latency of 300 ms, and an execution duration of 100 ms, each javascript element should take around 400ms to execute. Multiply that by 10 elements, and we get a ~4000 ms page load time. This is our worst-case scenario.\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Apache-remote-without-prefetching\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eApache/remote without prefetching\u003c/h3\u003eAssuming we modeled the latency accurately with our local Python webserver (which we didn't), these should be about the same as the local results. Each Javascript load is 50-60ms faster, however. This can be chalked up to Apache being just plain better than our local server.\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Python-local-with-prefetching\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003ePython/local with prefetching\u003c/h3\u003eIn this case, we shave about 1 second off our overall page load time. By examining the server output, it is clear that the page is sending off its prefetch requests all at the start of the page load, and the files are downloaded in the network thread. However, since the server cannot handle parallel connections/requests, the files must be read in serial. In this case, it looks like the prefetches are around 100ms ahead of the execution in the UI thread. Since we can load and execute at the same time, that 100ms stacks to give us a savings of around a second. Pretty good!\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Apache-remote-with-prefetching\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eApache/remote with prefetching\u003c/h3\u003eIn this case, since Apache can handle multiple concurrent connections, the browser can shoot off all its requests at once. Once again, the loading is a little behind the execution of the scripts, but since we are downloading them all concurrently, we've finished fetching the scripts by the time the second one starts executing. Each subsequent script therefore only takes execution time (no downloading needed), so we get excellent savings, very close to our optimal page load time of ~1200-1300 ms.\u003ch3 style\u003d\"font-weight:normal;color:rgb(68,68,68);font-size:1.4em\"\u003e\u003ca name\u003d\"TOC-Costs\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eCosts\u003c/h3\u003eAdding the X-subresource headers can be costly. In this case, it increased the size of the headers on \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003etest5.html\u003c/code\u003e from 166 bytes to 747 bytes. The appended headers were:\u003cpre\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\r\nX-subresource: test5_1.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_2.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_3.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_4.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_5.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_6.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_7.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_8.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_9.js; type\u003dapplication/x-javascript\r\nX-subresource: test5_10.js; type\u003dapplication/x-javascript\r\n\u003c/code\u003e\r\n\u003c/pre\u003eNote that the current implementation of the extension doesn't use any of the metadata included in the header (it just sends off a blind request), so that could be eliminated. Additionally, these could be concatenated into one large X-subresource header:\u003cpre\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\r\nX-subresource: test5_1.js, test5_2.js, test5_3.js, test5_4.js, test5_5.js, test5_6.js, test5_7.js, test5_8.js, test5_9.js, test5_10.js\r\n\u003c/code\u003e\r\n\u003c/pre\u003eThis would bring the size of the header down to 302 bytes. While much more reasonable, this is not insignificant. However, as plaintext, it's a good candidate for an optimization like gzip'd headers.\u003ch1\u003e\u003ca name\u003d\"TOC-Conclusions\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eConclusions\u003c/h1\u003eWhen prefetching is enabled (as in the 1st row of results), the browser doesn't have to block network loads on executing javascript. It can read the prefetch headers, send off requests, and forget about them --- they'll continue in the network thread while work is being done in the UI thread.\u003cp\u003eThe most fruitful type of sub-resource to be prefetched is probably Javascript; when the browser encounters an external JS file, it has to block the main/UI thread until the file is downloaded and executed. If, however, the file has been prefetched, the time taken to download is instant savings on the overall load time of the page. In a case like this, with multiple consecutive scripts, the difference can be dramatic.\u003c/p\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Future-Work\" style\u003d\"color:rgb(0,51,204);text-decoration:underline\" /\u003eFuture Work\u003c/h1\u003eSome areas of future work include:\u003cul\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003eTesting with a dummynet for varying network bandwidth, RTT, and loss rate.\u003c/li\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003eWriting an Apache module that generates X-subresource headers\u003c/li\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003eRe-writing the extension in C++\u003c/li\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003eGetting it to work with images and style sheets\u003c/li\u003e\u003cli style\u003d\"list-style-position:outside;list-style-type:square\"\u003eMaking it more robust in the face of strange cache settings (or, more generally, knowing when prefetching will make the user experience worse)\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3000393748807839342"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/x-subresources/x-subresources-1"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8913230392167253636"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8913230392167253636"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8913230392167253636"}],"author":[{}],"sites$pageName":{"$t":"x-subresources-1"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5845559096806026491"},"published":{"$t":"2014-12-10T07:42:51.585Z"},"updated":{"$t":"2014-12-10T07:42:51.623Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-10T07:42:51.585Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2014-12-10 at 9.42.17 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5845559096806026491"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6741104919391183800"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/telemetry/diagnosing-test-failures/Screen%20Shot%202014-12-10%20at%209.42.17%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5845559096806026491"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5845559096806026491"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5845559096806026491"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5845559096806026491"}],"author":[{"name":{"$t":"Jeremy Moskovich"},"email":{"$t":"jeremy@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5640028138331922371"},"published":{"$t":"2013-11-12T06:01:17.011Z"},"updated":{"$t":"2014-12-09T02:34:03.181Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-14T09:12:34.504Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"ActiveDOMObject"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cb\u003e\u003cfont color\u003d\"#ff0000\"\u003eDRAFT. NEEDS REVIEW\u003c/font\u003e\u003c/b\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe ActiveDOMObject is used to implement DOM objects that \u003cspan style\u003d\"font-size:10pt\"\u003ecan involve asynchronous operations such as loading data from network (e.g. XMLHttpRequest, WebSocket) to\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003ekeep them alive while async op is active\u003c/li\u003e\u003cli\u003ehold back actions resulting from async op while the document is suspended\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eThe ActiveDOMObject\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e classes can override its hasPendingActivity() method to keep the object alive while some async operation is in progress. As long as hasPendingActivity() returns true, V8 prolongs its life so that it doesn't get garbage collected even when it becomes unreachable. Note that there must be a V8 wrapper for the object in order to this to work. \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eWhile hasPendingActivity() returns true, the life of the parent Document object is also prolonged (explanation TBA). You rarely need to override contextDestroyed() for ActiveDOMObject subclasses.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eActiveDOMObjects are notified of detach of the parent Document object (or shutdown of the parent WorkerThread) as the stop() method called on it. Commonly, they \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt\"\u003estart shutdown of the asynchronous operation in stop() if any. This detach occurs regardless of hasPendingActivity().\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003esuspend() is called when dialogs such as alert(), prompt(), etc. are going to be shown or the WebInspector's pause is going to be active. resume() is called when the dialog is closed or the WebInspector resumes script execution. Between suspend() and resume(), it's recommended that operations on the ActiveDOMObjects are suspended. Since resource loading is automatically suspended by Chrome's resource dispatched code, you may not need to manually hold back async method calls.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen implementing, it is critical that you also add ActiveDOMObject to the interface flags in your IDL file, or GC will pay no attention to hasPendingActivity()!\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs of Nov 12 2013 by tyoshino@. Updated July 17, 2014 by kouhei@\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eThanks haraken@, abarth@\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2023764670965291136"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/blink/activedomobject"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5640028138331922371"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5640028138331922371"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5640028138331922371"}],"author":[{"name":{"$t":"Takeshi Yoshino"},"email":{"$t":"tyoshino@chromium.org"}}],"sites$pageName":{"$t":"activedomobject"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"},"published":{"$t":"2013-01-18T18:49:51.968Z"},"updated":{"$t":"2014-12-05T17:05:57.489Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-05T17:05:51.674Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Lenovo Thinkpad X131e Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction1\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eEntering\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-USB-Boot\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eUSB Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eLegacy Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003eLeaving\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Servo-Header\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eServo Header\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"http://www.google.com/intl/en/chrome/education/devices/lenovo-x131e-chromebook.html\"\u003eLenovo Thinkpad X131e Chromebook\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eAn unrelated note: Holding just Refresh and poking the Power button hard-resets the machine without entering Recovery. That's occasionally useful, but use it with care - it doesn't sync the disk or shut down politely, so there's a nonzero chance of trashing the contents of your stateful partition.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Introduction1\" /\u003eIntroduction\u003c/h3\u003e\r\n\u003cp\u003eEnabling Developer mode is the first step to tinkering with your Chromebook. With Developer mode enabled you can do things like poke around on a command shell (as root if you want), install Chromium OS, or try other OS's. Note that Developer mode turns off some security features like verified boot and disabling the shell access. If you want to browse in a safer, more secure way, leave Developer mode turned OFF. Note: Switching between Developer and Normal (non-developer) modes will remove user accounts and their associated information from your Chromebook.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Entering\" /\u003eEntering\u003c/h3\u003e\r\n\u003cp\u003eOn this device, both the recovery button and the dev-switch have been virtualized. Our partners don't really like physical switches - they cost money, take up space on the motherboard, and require holes in the case.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eThis device has unique requirements for entering recovery mode!\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eYou must first remove all power from the system, both the battery and the AC plug. Then when power is re-applied you have 20 seconds to enter recovery mode with the ESC+Refresh+Power button sequence.\u003c/p\u003e\r\n\u003cp\u003eIn this system the removal of power sources will force the Embedded Controller to restart and stay in read-only code to ensure the recovery mode is secure.\u003c/p\u003e\r\n\u003cp\u003eTo invoke Recovery mode, you hold down the \u003cfont color\u003d\"#990000\"\u003eESC\u003c/font\u003e and \u003cfont color\u003d\"#990000\"\u003eRefresh\u003c/font\u003e (F3) keys and poke the \u003cfont color\u003d\"#990000\"\u003ePower\u003c/font\u003e button.\u003c/p\u003e\r\n\u003cp\u003eTo enter Dev-mode you first invoke Recovery, and at the Recovery screen press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e (there's no prompt - you have to know to do it). It will ask you to confirm, then reboot into dev-mode.\u003c/p\u003e\r\n\u003cp\u003eDev-mode works the same as always: It will show the scary boot screen and you need to press \u003cfont color\u003d\"#990000\"\u003eCtrl-D\u003c/font\u003e or wait 30 seconds to continue booting.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-USB-Boot\" /\u003eUSB Boot\u003c/h3\u003e\r\n\u003cp\u003eBy default, USB booting is disabled. Once you are in Dev-mode and have a root shell, you can run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo crossystem dev_boot_usb\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot from USB drives with Ctrl-U.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot\" /\u003eLegacy Boot\u003c/h3\u003e\r\n\u003cp\u003eSorry, but this device does not support a legacy BIOS mode.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Leaving\" /\u003eLeaving\u003c/h3\u003e\r\n\u003cp\u003eTo leave Dev-mode and go back to normal mode, just follow the instructions at the scary boot screen. It will prompt you to confirm.\u003c/p\u003e\r\n\u003cp\u003eIf you want to leave Dev-mode programmatically, you can run \u003ccode\u003ecrossystem disable_dev_request\u003d1; reboot\u003c/code\u003e from a root shell. There's no way to enter Dev-mode programmatically, and just seeing the Recovery screen isn't enough - you have to use the three-finger salute which hard-resets the machine first. That's to prevent a remote attacker from tricking your machine into dev-mode without your knowledge.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e and \u003ca href\u003d\"http://www.denx.de/wiki/U-Boot\" rel\u003d\"nofollow\"\u003eDas U-Boot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-stout-2817.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e and the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/u-boot/+/firmware-stout-2817.B\"\u003eChromium OS u-boot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-stout-2817.B\u003c/code\u003e branches.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable. DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003cp\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003e\u003ca href\u003d\"http://www.youtube.com/watch?feature\u003dfvwp\u0026amp;NR\u003d1\u0026amp;v\u003dFj3WBfRZ5Nc\u0026amp;t\u003d0m31s\"\u003eStop.\u003c/a\u003e \u003c/b\u003e\u003c/font\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003e\u003ca href\u003d\"http://www.youtube.com/watch?feature\u003dfvwp\u0026amp;NR\u003d1\u0026amp;v\u003dFj3WBfRZ5Nc\u0026amp;t\u003d0m31s\"\u003eDon't.\u003c/a\u003e \u003c/b\u003e\u003c/font\u003e\u003cb style\u003d\"font-size:medium\"\u003e\u003ca href\u003d\"http://www.youtube.com/watch?feature\u003dfvwp\u0026amp;NR\u003d1\u0026amp;v\u003dFj3WBfRZ5Nc\u0026amp;t\u003d0m31s\"\u003eCome back.\u003c/a\u003e\u003c/b\u003e\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\"\u003eReally.\u003c/font\u003e Opening the case will allow you to modify the read-only firmware that makes recovery possible. If someone from \"teh internets\" says \"You need to reflash your BIOS\", they're almost certainly wrong.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged. If you have hardware troubles, please seek assistance first from an authorized center. Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first. If you just want to see what the inside looks like, gaze upon this (click for a high res version):\u003c/p\u003e\r\n\r\n\u003cp style\u003d\"text-align:center\"\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-inside-top.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1399404987520/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-inside-top.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-inside-bottom.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1399404999723/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-inside-bottom.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-bare-top.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1399405008897/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-bare-top.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-bare-bottom.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1399405018569/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-bare-bottom.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Servo-Header\" /\u003eServo Header\u003c/h3\u003e\u003cdiv\u003eThe X131e was not designed to use \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eservo\u003c/a\u003e. A small number of debug units have a hand-wired header.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7616793841804860184"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"lenovo-thinkpad-x131e-chromebook"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1940742749634908378"},"published":{"$t":"2014-12-04T18:55:40.786Z"},"updated":{"$t":"2014-12-04T18:55:40.786Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-04T18:55:40.786Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1940742749634908378"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1940742749634908378"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1940742749634908378"}],"author":[{"name":{"$t":"Marc-Antoine Ruel"},"email":{"$t":"maruel@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/document/d/1IQMoBeZe8cKjaCf4VIlj2AIt5ZBEsVfrh4o7DP1MPo0/edit#heading\u003dh.xt2hz3y9j243\"\u003eSwarming Postmortem: 2014-12-04\u003c/a\u003e"},{"index":"B","name":"Date","$t":"2014-12-04"}]},{"gd$etag":"\"USl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1838605870018848436"},"published":{"$t":"2011-08-26T16:16:04.510Z"},"updated":{"$t":"2014-12-03T18:52:30.359Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-03T18:52:28.627Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"How Extension Docs Are Served"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eThe documentation for Chrome extensions and apps is served at \u003ca href\u003d\"https://developer.chrome.com/extensions\"\u003edeveloper.chrome.com/extensions\u003c/a\u003e and \u003ca href\u003d\"https://developer.chrome.com/apps\"\u003edeveloper.chrome.com/apps\u003c/a\u003e by Google App Engine.\r\n\u003cdiv\u003eSee \u003ca href\u003d\"https://cs.\" rel\u003d\"nofollow\"\u003ehttps://\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ecs.\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"http://chromium.org/chrome/common/extensions/docs/README\"\u003echromium.org/chrome/common/extensions/docs/README\u003c/a\u003e to learn how the extension/app docs are generated.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Contributing-documentation\" /\u003eContributing documentation\u003c/h2\u003e\r\n\u003cdiv\u003eHave you found an error in the documentation? Either submit a patch (see below) or file a bug with label \u003ccode\u003eCr-Platform-Extensions\u003c/code\u003e at the \u003ca href\u003d\"https://code.google.com/p/chromium/issues/list\"\u003ethe issue tracker\u003c/a\u003e.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003eCheck out Chromium's source code, see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code\"\u003eGet the Code: Checkout, Build, Run \u0026amp; Submit\u003c/a\u003e (\u003ccode\u003egclient runhooks\u003c/code\u003e is optional for this purpose).\u003c/li\u003e\r\n\u003cli\u003eFind the relevant file that you need to edit (e.g. by visiting \u003ca href\u003d\"http://cs.chromium.org\"\u003ecs.chromium.org\u003c/a\u003e and pasting a quoted snippet from the page that you want to edit).\u003c/li\u003e\r\n\u003cli\u003eTo view the documentation locally, run \u003ccode\u003esrc/chrome/common/extensions/docs/server2/preview.py\u003c/code\u003e (this will serve the documentation at http://localhost:8888, add \u003ccode\u003e-p [port]\u003c/code\u003e to serve on a different port).\u003c/li\u003e\r\n\u003cli\u003eAfter updating the documentation, upload the patch to codereview.chromium.org (see also: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/contributing-code\"\u003eContributing Code\u003c/a\u003e).\u003c/li\u003e\r\n\u003cli\u003eOthers can preview your changes by visiting \u003ccode\u003ehttps://chrome-apps-doc.appspot.com/_patch/\u003ci\u003e[issue id]\u003c/i\u003e/extensions/\u003c/code\u003e (or /apps/).\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3443725574767880072"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/how-the-extension-system-works/docs/how-docs-are-served"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1838605870018848436"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1838605870018848436"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1838605870018848436"}],"author":[{}],"sites$pageName":{"$t":"how-docs-are-served"},"sites$revision":{"$t":"18"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/455628453897768619"},"published":{"$t":"2014-12-02T05:01:15.440Z"},"updated":{"$t":"2014-12-02T18:40:33.510Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-12-02T18:40:33.510Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"redirect.xml"},"summary":{},"content":{"type":"text/xml","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/455628453897768619"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/618862570500136737"},{"rel":"alternate","type":"text/xml","href":"https://sites.google.com/a/chromium.org/dev/sts/redirect.xml"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/455628453897768619"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/455628453897768619"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/455628453897768619"},{"rel":"edit-media","type":"text/xml","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/455628453897768619"}],"author":[{"name":{"$t":"Lucas Garron"},"email":{"$t":"lgarron@chromium.org"}}],"sites$revision":{"$t":"8"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7344814787681839589"},"published":{"$t":"2010-05-05T15:02:54.534Z"},"updated":{"$t":"2014-12-02T04:37:19.417Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-05-05T15:02:54.534Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"email.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7344814787681839589"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/738999279112213088"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/hsts/email.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7344814787681839589"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7344814787681839589"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7344814787681839589"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7344814787681839589"}],"author":[{"name":{"$t":"Adam Langley"},"email":{"$t":"agl@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"Wil7JmA_\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9072629750625292687"},"published":{"$t":"2012-10-18T18:29:12.052Z"},"updated":{"$t":"2014-11-25T15:11:06.150Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-25T15:11:04.863Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Blink Core Projects"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cb\u003e\u003cfont size\u003d\"2\" style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis list is for Blink work that is about improving performance, infrastructure and/or the maintainability of the codebase. This is a list of high-priority projects that have minimal dependence on web standards bodies.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf you decide to take on one of these projects put your name at the beginning like [ ojan ]. Some of the bigger projects could use multiple people working on them.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTalk to Ojan if you have questions about any of these or want to add more things to this list. If you discover other new projects that would fit well here we should add them! \u003c/span\u003e\u003c/font\u003e\u003c/b\u003e\u003cb style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/b\u003e\u003cbr style\u003d\"background-color:transparent\" /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-blink-core-projects\" /\u003e\u003cspan\u003eblink/core projects\u003c/span\u003e\u003c/h2\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:disc;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13.3333330154419px;white-space:normal\"\u003e\u003cfont size\u003d\"2\" style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ePlease see the \u003ca href\u003d\"https://code.google.com/p/chromium/issues/list?can\u003d2\u0026amp;q\u003dlabel%3AProject-Warden\u0026amp;colspec\u003dID+Pri+M+Iteration+ReleaseBlock+Cr+Status+Owner+Summary+OS+Modified\u0026amp;cells\u003dtiles\"\u003eProject Warden list\u003c/a\u003e for more maintainability tasks.\u003c/span\u003e\u003c/font\u003e\u003c/b\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eIdentify and fix scrolling performance problems on this page: \u003c/span\u003e\u003ca href\u003d\"http://code.google.com/p/chromium/issues/detail?id\u003d157016\" style\u003d\"font-size:10pt;background-color:transparent\"\u003ehttp://crbug.com/157016\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent\"\u003eMoving widget-loading (iframes/plugins) out of the rendering tree \u003c/span\u003e\u003ca href\u003d\"http://wkb.ug/45049\" style\u003d\"font-size:10pt;color:rgb(17,85,204);font-family:arial,sans-serif;background-color:transparent\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003ewkb.ug/45049\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial;font-size:small;background-color:transparent\"\u003eAdd more invariants during layout to ensure proper behavior (see \u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d49019\" style\u003d\"font-family:arial;font-size:small;background-color:transparent\" rel\u003d\"nofollow\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d49019\u003c/a\u003e\u003cspan style\u003d\"font-family:arial;font-size:small;background-color:transparent\"\u003e and \u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d64222\" style\u003d\"font-family:arial;font-size:small;background-color:transparent\" rel\u003d\"nofollow\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d64222\u003c/a\u003e\u003cspan style\u003d\"font-family:arial;font-size:small;background-color:transparent\"\u003e)\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Performance\" /\u003ePerformance\u003c/h2\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e[META] RoboHornet (and RoboHornet Pro) related performance issues: \u003c/span\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d98798\" rel\u003d\"nofollow\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d98798\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:normal\"\u003e\u003cli style\u003d\"list-style-type:disc;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px\"\u003e- tag-based collections are invalidated on every add/remove of an \u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:13px\"\u003eelement (25%+ win for RoboHornetPro) \u003c/span\u003e\u003ca href\u003d\"http://wkb.ug/98823\" style\u003d\"color:rgb(17,85,204);font-family:arial,sans-serif;font-size:13px\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003ewkb.ug/98823\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImprove performance of Dromaeo and dom_perf bencharks. For example, \u0026lt;\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d99197\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d99197\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u0026gt; makes JSC go 40% faster on dom-traverse.  Can we do something similar for V8?\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline\"\u003e\u003cfont\u003e\u003cfont face\u003d\"Arial, sans-serif\"\u003e\u003cspan style\u003d\"line-height:18px\"\u003eShould report private memory on the perf bots: \u003ca href\u003d\"http://crbug.com/163280\"\u003ehttp://crbug.com/163280\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eImprove memory usage of the following benchmarks:\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:normal;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:circle;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003ca href\u003d\"http://build.chromium.org/f/chromium/perf/xp-release-dual-core/memory/report.html?history\u003d50\u0026amp;rev\u003d-1\u0026amp;graph\u003dcommit_charge\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttp://build.chromium.org/f/chromium/perf/xp-release-dual-core/memory/report.html?history\u003d50\u0026amp;rev\u003d-1\u0026amp;graph\u003dcommit_charge\u003c/span\u003e\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:circle;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003ca href\u003d\"http://build.chromium.org/f/chromium/perf/xp-release-dual-core/moz/report.html?history\u003d50\u0026amp;rev\u003d-1\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003ehttp://build.chromium.org/f/chromium/perf/xp-release-dual-core/moz/report.html?history\u003d50\u0026amp;rev\u003d-1\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:circle;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003ca href\u003d\"http://build.chromium.org/f/chromium/perf/xp-release-dual-core/intl1/report.html?history\u003d50\u0026amp;rev\u003d-1\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003ehttp://build.chromium.org/f/chromium/perf/xp-release-dual-core/intl1/report.html?history\u003d50\u0026amp;rev\u003d-1\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:circle;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003ca href\u003d\"http://build.chromium.org/f/chromium/perf/xp-release-dual-core/intl2/report.html?history\u003d50\u0026amp;rev\u003d-1\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003ehttp://build.chromium.org/f/chromium/perf/xp-release-dual-core/intl2/report.html?history\u003d50\u0026amp;rev\u003d-1\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:circle;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003ca href\u003d\"http://build.chromium.org/f/chromium/perf/xp-release-dual-core/bloat-http/report.html?history\u003d50\u0026amp;rev\u003d-1\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttp://build.chromium.org/f/chromium/perf/xp-release-dual-core/bloat-http/report.html?history\u003d50\u0026amp;rev\u003d-1\u003c/span\u003e\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eCreate (and then optimize) benchmarks that accurately represent memory usage in gmail, docs, etc.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eImprove performance test suites:\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003efirst and second tabs of dromaeo benchmarks show the same data: \u003c/span\u003e\u003c/font\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d160321\" style\u003d\"font-family:Arial;font-weight:normal;white-space:pre-wrap\"\u003ehttp://crbug.com/160321\u003c/a\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline\"\u003epage cyclers should have subgraphs for each individual site: \u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d161837\"\u003ehttp://crbug.com/161837\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003eadd performance trybots: \u003ca href\u003d\"http://crbug.com/120380\"\u003ehttp://crbug.com/120380\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003eLinux lowmem perf bot exhibits bimodal behavior: \u003ca href\u003d\"http://crbug.com/159077\"\u003ehttp://crbug.com/159077\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eexplore ways to reduce performance test variance: \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/161844\" style\u003d\"background-color:transparent;font-size:10pt\"\u003ehttp://crbug.com/161844\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Infrastructure\" /\u003eInfrastructure\u003c/h2\u003e\u003cul style\u003d\"font-weight:normal;font-family:Times New Roman;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:10pt;font-family:Times New Roman;background-color:transparent\"\u003erebaselining with virtual test suites involved gets confused: \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/237701\" style\u003d\"font-size:10pt;font-family:Times New Roman;background-color:transparent\"\u003ecrbug.com/237701\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003eSwitch chromium windows bots back to using Apache: \u003c/font\u003e\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d101373\" rel\u003d\"nofollow\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d101373\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eImprove garden-o-matic:\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003elet you minimize failures so they're not in your face:\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d97949\" style\u003d\"font-size:small;background-color:transparent;font-family:Arial\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(0,0,0);background-color:transparent;text-decoration:initial;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d97949\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eshow the last revision process by every layout test bot and the last by every non-layout test bot:\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d98088\" style\u003d\"font-size:small;background-color:transparent;font-family:Arial\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"background-color:transparent;color:rgb(0,0,0);text-decoration:initial;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;color:rgb(17,85,204);vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d98088\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003egarden-o-matic should run even if you don't have the server running locally: \u003ca href\u003d\"http://crbug.com/241506\"\u003ecrbug.com/241506\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cul style\u003d\"font-weight:normal;font-family:Times New Roman;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cul /\u003e\u003c/ul\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cb\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAdd a tool to garden-o-matic/flakiness dashboard/code review tool to make it possible to easily view the diff of an expected result to another platform's expected file (e.g. diff between platform/chromium/foo-expected.txt and platform/mac/foo-expected.txt).\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/b\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eRebaseline tests from the results.html page:\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d86797\" style\u003d\"font-size:small;background-color:transparent;font-family:Arial\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(0,0,0);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d86797\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cb\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cb style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:10pt;background-color:transparent\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:normal;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eFlakiness dashboard\u003c/font\u003e\u003c/span\u003e\u003c/b\u003e\u003c/li\u003e\u003c/b\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003egtests should output the same JSON format as run-webkit-tests: \u003ca href\u003d\"http://crbug.com/247192\"\u003ecrbug.com/247192\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eflakiness dashboard links on the waterfall point to the wrong data: \u003ca href\u003d\"http://crbug.com/246849\"\u003ecrbug.com/246849\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eAnnotate the failing test results shown in the flakiness dashboard with the revision it last failed at. Something like: r12345\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eAudio failures don't show up correctly on the flakiness dashboard: \u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d104632\" rel\u003d\"nofollow\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d104632\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cb\u003e\u003cfont size\u003d\"2\" style\u003d\"font-weight:normal\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/b\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-LayoutTests\" /\u003eLayoutTests\u003c/h2\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eCreate infrastructure for red-green layout tests. They have no expected result. If the bitmap has only green and white pixels, it passes, otherwise it fails.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:small;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMake the text caret not blink in tests:\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d97558\" style\u003d\"font-size:small;font-family:Arial;background-color:transparent\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d97558\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eusing js-test-pre.js should only require a DOCTYPE and js-test-pre.js:\u003c/span\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d48344\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(0,0,0);background-color:transparent;text-decoration:initial;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d48344\u003c/span\u003e\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"font-family:Arial;font-weight:normal;list-style-type:disc;background-color:transparent;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHundreds of mac failures are due to a slightly different color repaint background: \u003c/span\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ca href\u003d\"https://bugs.webkit.org/show_bug.cgi?id\u003d83400\" rel\u003d\"nofollow\"\u003ehttps://bugs.webkit.org/show_bug.cgi?id\u003d83400\u003c/a\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eHundreds of MountainLion-only reftest failures: \u003ca href\u003d\"http://crbug.com/238093\"\u003ecrbug.com/238093\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003echeckLayout() should error out if no data-expected* attributes were found: \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/233956\"\u003ecrbug.com/233956\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eInspector tests are crazy slow in debug: \u003ca href\u003d\"http://crbug.com/238095\"\u003ecrbug.com/238095\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/webkit-core-projects"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9072629750625292687"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9072629750625292687"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9072629750625292687"}],"author":[{"name":{"$t":"Ojan Vafai"},"email":{"$t":"ojan@chromium.org"}}],"sites$pageName":{"$t":"webkit-core-projects"},"sites$revision":{"$t":"33"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8700526231475487650"},"published":{"$t":"2014-11-21T04:59:54.848Z"},"updated":{"$t":"2014-11-21T04:59:54.848Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-21T04:59:54.848Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7582987878577786924"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8700526231475487650"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8700526231475487650"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8700526231475487650"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Brand \u0026 Model Number","$t":"HP Compaq 6720s"},{"index":"B","name":"Wifi","$t":"?"},{"index":"C","name":"Ethernet","$t":""},{"index":"D","name":"Trackpad","$t":""},{"index":"E","name":"Suspend/Resume","$t":""},{"index":"F","name":"Comments \u0026 Caveats","$t":"touchpad does not work"},{"index":"G","name":"Contact","$t":"joeboy95619@gmail.com"},{"index":"H","name":"Buy Link","$t":""}]},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9209060597174585161"},"published":{"$t":"2010-10-15T02:16:04.387Z"},"updated":{"$t":"2014-11-18T23:14:20.603Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-10-15T02:29:36.087Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Print Preview"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Status:-Draft-as-of-2010-10-14.\" /\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:19px\"\u003e\u003cspan style\u003d\"font-weight:normal;font-size:15px\"\u003eStatus: Draft as of 2010/10/14.\u003c/span\u003e\u003c/span\u003e\u003c/font\u003e\u003c/h3\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Objective\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eObjective\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eA feature in Chrome to let users see their printer output before sending it to the printer.\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Background\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eBackground\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eWeb\r\n pages are generally designed to be displayed on a computer screen and \r\nare not always optimized for printing. When a web page gets printed, the\r\n browser has to reformat the page\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eto\r\n fit the physical constraints of the paper media. The web page printed \r\nto paper may look very different from what users see on the screen. Thus\r\n users need to be have a print preview feature in order to verify their \r\nprint jobs before sending them off to the printer, so they do not waste \r\nconsumables like ink and paper.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eAs\r\n of October 2010, all major browsers have a print preview feature which \r\nlets users see what their print jobs will look like. The only exception \r\nis Chrome. The current implementation of printing in Chrome pops up a \r\nnative printer selection dialog, where the user can select a destination\r\n printer and change printer settings. Once the user selects print from \r\nthe native printing dialog, Chrome generates a print job and sends it \r\noff to the printer.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eOverview\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eFor\r\n print preview in Chrome, the plan is to display the print preview in a \r\nnew tab which is a DOM UI page. The print preview page will consist of a\r\n left pane that allows for printer selection and printer options, and a \r\nright pane for displaying the preview as well as page thumbnails.\u003c/span\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eMocks: TODO(thestig) [insert pictures here]\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eTo\r\n generate a preview that most closely resembles what will be printed, \r\nChrome will generate a PDF document to be sent to the printer and \r\ndisplay it as the preview. Chrome will leverage the existing PDF plugin \r\nit ships with to render the PDF to screen.\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-User-Experience\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eUser Experience\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eUsers\r\n should be able to select print as they currently do with the wrench \r\nmenu, renderer context menu, and shortcut key to bring up a print \r\npreview tab. In the print preview tab, the left pane will have a drop \r\ndown list to select printers that are currently available through the \r\nnative print dialog. Below the printer selection drop down is a list of \r\ncommonly used options, including the pages to print, the number of \r\ncopies, and portrait/landscape modes. A ‘More options’ button expands \r\nthe options list to show advances options when clicked.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eAs\r\n the user adjusts the options, the preview on the right updates to \r\nreflect the new options the user selects. When the user finishes \r\npreviewing, the user can hit the print button to print the document or \r\nthe cancel button to exit the print preview. In addition, there will be a\r\n button so the user can access the native print dialog. TODO(UI) - \r\nfigure out details.\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Related-Work\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eRelated Work\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThere\r\n is ongoing work to implement a PDF backend for Skia. This backend will \r\nenable Chrome to render web pages to consistent and size-efficient PDFs \r\non Windows and Linux, which have no PDF generation capabilities and poor\r\n PDF generation capabilities, respectively. Mac OS X already has a high \r\nfidelity PDF backend built-in.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThere is ongoing work to improve the PDF plugin with additional features like page thumbnails.\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Implementation\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eImplementation\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n print preview feature consists of both frontend work to provide the \r\ndesired interactive user experience and backend work to generate the PDF\r\n and talk to the printers. Another area to consider is persistent on \r\ndisk data.\u003c/span\u003e\u003cbr /\u003e\u003ch5\u003e\u003ca name\u003d\"TOC-Frontend\" /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eFrontend\u003c/span\u003e\u003c/h5\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n front end work starts with hooking up the various print commands and \r\nhot keys to display a new tab that loads chrome://print. There will be a\r\n manager for print preview TabContents so each existing printable tab \r\nonly has at most one print preview tab. Pressing print on a page that \r\nalready has a preview tab will just bring the preview tab into focus. \r\nThe print preview tab closes automatically when the user prints or \r\ncancels. Print preview tabs themselves are not printable.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewManager\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e will be similar to the \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eDevToolsManager\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e. There is a single instance that lives inside \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eBrowserProcess\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e and shares its lifetime. It keeps a mapping of \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eTabContents\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e and their associated \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewUIs\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e. The print event handler will ask the \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewManager\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e for a \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewUI\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e for a given existing tab. The \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewManager\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e will either create a new print preview tab and return it or return an existing print preview tab. Since the \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewManager\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e knows which tabs are print preview tabs, it will not create a \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewUI\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e for another \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrintPreviewUI\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n print preview tab uses DOM UI to construct a special web page that has \r\nprivileges to communicate with the browser process. It uses IPC to talk \r\nto the browser process to get the list of printers and set the the \r\nselected printer. It also needs to get the html snippet for the options \r\nfor the selected printer from the browser, and send updates as the user \r\nselects options that affects the print output.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cimg height\u003d\"406px;\" src\u003d\"https://lh6.googleusercontent.com/o6Bxn-bQokkswehLoGiZbhn9UfjyNCsyYDOg8hmGIh5sOm2bftvqQM33zZFj4zYR4s04ULbSJPNIP5YX_wUw0r7LaEHrIWXxbti6__vI6U-V1ObMIw\" width\u003d\"633px;\" /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n frontend also embeds a PDF plugin to display the preview. The browser \r\ngenerates the PDF and make it available to the print preview UI via a \r\nspecial URL, i.e. chrome://print/foo, so the UI just needs to create \r\n\u0026lt;embed\u0026gt; tag with the appropriate src parameter. The front end also\r\n needs to communicate with the PDF plugin to keep the list of pages to \r\nprint in sync with the thumbnail selection inside the plugin. The DOM UI\r\n will communicate with the plugin via a Pepper API. TODO(thestig) talk \r\nto PDF plugin folks about interfacing with the plugin.\u003c/span\u003e\u003cbr /\u003e\u003ch5\u003e\u003ca name\u003d\"TOC-Backend\" /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eBackend\u003c/span\u003e\u003c/h5\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe backend code in the browser process needs to do the heavy lifting to support all the requests coming from the front end.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eTo\r\n start, the browser process needs to get the list of printers and \r\nprinter options using platform specific APIs. Cloud print already has \r\ncode to generate html options code from a PPD/XPS, which is useful here.\r\n Though to make this work on Windows XP, which does support XPS, the \r\nbrowser also need to be able to query for common options from printers.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n majority of the work in the backend involves restructuring the messy \r\nprinting pipeline to support preview. The current Linux printing \r\npipeline works differently from Windows and Mac. Once all the platforms \r\nare brought in line, the printing pipeline needs to be broken up into \r\ntwo pieces: PDF generation and printing. The current printing pipeline \r\nwaits for the user to select a printer before generating the print \r\noutput using platform specific code and sending the output to the \r\nprinter. The actual printing process uses pipelining: the renderer \r\ngenerates printing metadata one page at a time, so it can generate them \r\nwhile the PrintJobWorker in the browser process sends them to the \r\nprinter at the same time.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cimg height\u003d\"349px;\" src\u003d\"https://lh5.googleusercontent.com/2z3HNh9XZnXodPVnCvwAPxo0t2XNuvA1WMR9btDaOPVnE7mnTHAAlcE_qgZeDvVqjBVEoBZGVwlEaW4T-nok5C8ifNomKSZcjMh3SXoUu3LDP88OcA\" width\u003d\"663px;\" /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eIn\r\n the printing work flow for print preview, the renderer needs to \r\nretrieve the current printer settings, generate a PDF, and send the PDF \r\nto the browser. On the browser side, it just displays the PDF and wait \r\nfor users to tweak the printer settings, after which the browser would \r\nask the renderer to generate a new PDF for previewing. This process \r\nrepeats until the user finishes with preview, after which Chrome sends \r\nthe final revision of the PDF to the printer. Whether this should be \r\ndone directly or by ask the plugin to do it through parts of the \r\nexisting printing pipeline remains TBD.\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003cimg height\u003d\"161px;\" src\u003d\"https://lh4.googleusercontent.com/AztOs3lb0beuoYTs6GRn-y-xpnJaCTL_GoJXE9Z3C_hxaLq5SrQB5qx9mqkrmwSbnHbxZqkMvbXHZLahm8EXTBPoXrbuNuknU62-VawahlHMvNP3Rw\" width\u003d\"717px;\" /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePoints to consider are:\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cul\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n printing pipeline needs to support both the current model and the new \r\nmodel while print preview development is a work in progress behind a \r\ncommand line flag.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePDF generation needs to happen in a reasonable amount of time to ensure print preview feels responsive to the user.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eAlternatively,\r\n we can generate the PDF as a set of one page PDFs, but the PDF viewer \r\nplugin needs to know how to display them together as one PDF.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eDuplicate the Frame/DOM/Render tree for printing? \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/21555\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,153);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:underline;vertical-align:baseline\"\u003ehttp://crbug.com/21555\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003ch5\u003e\u003ca name\u003d\"TOC-Persistent-On-Disk-Data\" /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePersistent On Disk Data\u003c/span\u003e\u003c/h5\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n print preview feature may need to save user settings for printers to \r\ndisk so they persist between print jobs. I.e. it would be annoying to \r\nhave to set the printer to landscape, black and white, with options foo \r\nand bar every time a user printers.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThese\r\n user preferences should be stored in a new database specifically for \r\nprinter settings. This is a better alternative to storing the data \r\ndirectly in the preferences file. A user with many printers can generate\r\n lots of printer setting data that can potentially make the preferences \r\nfile much bigger. This impacts start up time since Chrome needs to load \r\nthe preferences file on start up, even though the printer settings are \r\nnot used until much later.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n proposed database will contain a table for global print preview \r\nsettings, like the most recently used printers. It will also have a \r\ntable for printer settings, where the columns are printer name, setting \r\nname, and setting value. Printer name and setting name should together \r\nform a unique key. In memory, the representation will be the same as \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ecloud_print::PrinterBasicInfo\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e’s \u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Courier New;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eoptions\u003c/span\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e variable.\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Internationalization\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eInternationalization\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eTODO / does the left pane need to be flipped around for RTL languages? Other i18n issues?\u003c/span\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Future-Enhancements\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eFuture Enhancements\u003c/span\u003e\u003c/h4\u003e\u003ch5\u003e\u003ca name\u003d\"TOC-Cloud-Printing-Integration\" /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eCloud Printing Integration\u003c/span\u003e\u003c/h5\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe\r\n initial version of print preview will only work with printers exposed \r\nby the OS. To integrate with Cloud Printing, Chrome will need to query \r\nfor cloud printers in additional to local printers via the cloud \r\nprinting APIs. Assuming print preview uses the same code as the cloud \r\nprinter server to parse PPD/XPS files and display options, Chrome just \r\nneed to get the printer info (PPD file) and available/default paper \r\nsizes. With these two pieces of data, Chrome can generate the option \r\ndialog and preview on its own. When the user hits the print button, \r\nChrome will simply send the PDF to the cloud print server instead of to a\r\n local printer.\u003c/span\u003e\u003cbr /\u003e\u003ch5\u003e\u003ca name\u003d\"TOC-Other-Enhancements\" /\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eOther Enhancements\u003c/span\u003e\u003c/h5\u003e\u003cul\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eAbility to adjust headers and footers.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eAbility to adjust margins.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eShrink/expand to fit page\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eIntegration with Google Docs.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eUI\r\n feature to search for printers by name - large companies may have many \r\nnetwork printers available which makes it hard to select from a list.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eLocation-aware printer selection.\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eSync print preview settings to the native dialog\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Privacy-and-Security-Concerns\" /\u003e\u003cspan style\u003d\"font-size:12pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:bold;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003ePrivacy and Security Concerns\u003c/span\u003e\u003c/h4\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline\"\u003eThe print preview page and the PDF plugin both run inside a sandboxed renderer process. The page does have special privileges to communicate with the browser \r\nprocess to get printer options and send it print jobs. Provide the \u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px\"\u003einterface between the renderer and the browser is carefully controlled, print preview should be as secure as any other renderer process.\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/print-preview"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9209060597174585161"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9209060597174585161"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9209060597174585161"}],"author":[{"name":{"$t":"Lei Zhang"},"email":{"$t":"thestig@chromium.org"}}],"sites$pageName":{"$t":"print-preview"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4793792899123546807"},"published":{"$t":"2014-11-18T17:10:30.970Z"},"updated":{"$t":"2014-11-18T17:10:31.013Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-18T17:10:30.970Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"process.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4793792899123546807"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/process.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4793792899123546807"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4793792899123546807"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4793792899123546807"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4793792899123546807"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1927750904831292193"},"published":{"$t":"2014-11-18T17:09:53.083Z"},"updated":{"$t":"2014-11-18T17:09:53.114Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-18T17:09:53.083Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"summarize.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1927750904831292193"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/summarize.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1927750904831292193"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1927750904831292193"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1927750904831292193"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1927750904831292193"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7886026231394464446"},"published":{"$t":"2014-11-18T17:07:34.696Z"},"updated":{"$t":"2014-11-18T17:07:34.846Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-18T17:07:34.696Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"04-information is.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7886026231394464446"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/04-information%20is.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7886026231394464446"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7886026231394464446"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7886026231394464446"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7886026231394464446"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6602922801889305223"},"published":{"$t":"2014-11-18T17:06:38.488Z"},"updated":{"$t":"2014-11-18T17:06:38.755Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-18T17:06:38.488Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"03-individual trace.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6602922801889305223"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/03-individual%20trace.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6602922801889305223"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6602922801889305223"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6602922801889305223"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6602922801889305223"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8959946275417361377"},"published":{"$t":"2014-11-18T17:05:20.818Z"},"updated":{"$t":"2014-11-18T17:05:20.866Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-18T17:05:20.818Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"02-lefttoright.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8959946275417361377"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/02-lefttoright.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8959946275417361377"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8959946275417361377"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8959946275417361377"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8959946275417361377"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8227016470112576463"},"published":{"$t":"2014-11-18T17:03:08.503Z"},"updated":{"$t":"2014-11-18T17:03:08.546Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-18T17:03:08.503Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"01-followalong.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8227016470112576463"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/01-followalong.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8227016470112576463"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8227016470112576463"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8227016470112576463"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8227016470112576463"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4274995553985884"},"published":{"$t":"2014-11-17T19:38:55.530Z"},"updated":{"$t":"2014-11-17T19:38:55.561Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:38:55.530Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"19-populated.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4274995553985884"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/19-populated.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4274995553985884"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4274995553985884"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4274995553985884"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4274995553985884"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/322329830268157300"},"published":{"$t":"2014-11-17T19:38:38.634Z"},"updated":{"$t":"2014-11-17T19:38:38.674Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:38:38.634Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"18-verylong.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/322329830268157300"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/18-verylong.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/322329830268157300"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/322329830268157300"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/322329830268157300"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/322329830268157300"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6194442754097769813"},"published":{"$t":"2014-11-17T19:38:19.340Z"},"updated":{"$t":"2014-11-17T19:38:19.368Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:38:19.340Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"17-loadrelatedjank.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6194442754097769813"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/17-loadrelatedjank.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6194442754097769813"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6194442754097769813"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6194442754097769813"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6194442754097769813"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8599859660769972227"},"published":{"$t":"2014-11-17T19:38:02.129Z"},"updated":{"$t":"2014-11-17T19:38:02.158Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:38:02.129Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"16-after.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8599859660769972227"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/16-after.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8599859660769972227"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8599859660769972227"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8599859660769972227"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8599859660769972227"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5060609048327673318"},"published":{"$t":"2014-11-17T19:37:39.982Z"},"updated":{"$t":"2014-11-17T19:37:40.012Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:37:39.982Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"15-difflayertree.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5060609048327673318"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/15-difflayertree.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5060609048327673318"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5060609048327673318"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5060609048327673318"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5060609048327673318"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5221960456201352938"},"published":{"$t":"2014-11-17T19:37:04.463Z"},"updated":{"$t":"2014-11-17T19:37:04.493Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:37:04.463Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"14-otherlayers.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5221960456201352938"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/14-otherlayers.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5221960456201352938"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5221960456201352938"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5221960456201352938"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5221960456201352938"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2963072814142881231"},"published":{"$t":"2014-11-17T19:36:36.625Z"},"updated":{"$t":"2014-11-17T19:36:36.657Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:36:36.625Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"13-recalc.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2963072814142881231"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/13-recalc.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2963072814142881231"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2963072814142881231"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2963072814142881231"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2963072814142881231"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3410614813475084620"},"published":{"$t":"2014-11-17T19:36:18.192Z"},"updated":{"$t":"2014-11-17T19:36:18.223Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:36:18.192Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"12-asusual.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3410614813475084620"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/12-asusual.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3410614813475084620"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3410614813475084620"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3410614813475084620"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3410614813475084620"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1344619409780435700"},"published":{"$t":"2014-11-17T19:35:58.128Z"},"updated":{"$t":"2014-11-17T19:35:58.162Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:35:58.128Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"11-investigation.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1344619409780435700"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/11-investigation.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1344619409780435700"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1344619409780435700"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1344619409780435700"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1344619409780435700"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6450931982565765562"},"published":{"$t":"2014-11-17T19:35:33.785Z"},"updated":{"$t":"2014-11-17T19:35:33.815Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:35:33.785Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"10-dramatically.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6450931982565765562"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/10-dramatically.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6450931982565765562"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6450931982565765562"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6450931982565765562"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6450931982565765562"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4793826485533319473"},"published":{"$t":"2014-11-17T19:34:56.834Z"},"updated":{"$t":"2014-11-17T19:34:56.867Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:34:56.834Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"09-layertree.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4793826485533319473"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/09-layertree.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4793826485533319473"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4793826485533319473"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4793826485533319473"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4793826485533319473"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4173204008927660465"},"published":{"$t":"2014-11-17T19:34:15.072Z"},"updated":{"$t":"2014-11-17T19:34:15.103Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:34:15.072Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"08-after.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4173204008927660465"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/08-after.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4173204008927660465"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4173204008927660465"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4173204008927660465"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4173204008927660465"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8681030098917795975"},"published":{"$t":"2014-11-17T19:33:31.504Z"},"updated":{"$t":"2014-11-17T19:33:31.533Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:33:31.504Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"07-hypothetsis.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8681030098917795975"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/07-hypothetsis.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8681030098917795975"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8681030098917795975"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8681030098917795975"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8681030098917795975"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3961981932953037455"},"published":{"$t":"2014-11-17T19:32:52.702Z"},"updated":{"$t":"2014-11-17T19:32:52.729Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:32:52.702Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"06-invalidation.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3961981932953037455"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/06-invalidation.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3961981932953037455"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3961981932953037455"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3961981932953037455"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3961981932953037455"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3404797967144826965"},"published":{"$t":"2014-11-17T19:32:24.427Z"},"updated":{"$t":"2014-11-17T19:32:24.453Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:32:24.427Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"05-tapdelay.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3404797967144826965"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/05-tapdelay.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3404797967144826965"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3404797967144826965"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3404797967144826965"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3404797967144826965"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2786306509228238080"},"published":{"$t":"2014-11-17T19:31:29.483Z"},"updated":{"$t":"2014-11-17T19:31:29.510Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:31:29.483Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"04-rects.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2786306509228238080"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/04-rects.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2786306509228238080"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2786306509228238080"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2786306509228238080"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2786306509228238080"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1832984028091782008"},"published":{"$t":"2014-11-17T19:30:24.071Z"},"updated":{"$t":"2014-11-17T19:30:24.100Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:30:24.071Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"03-zoom.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1832984028091782008"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/03-zoom.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1832984028091782008"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1832984028091782008"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1832984028091782008"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1832984028091782008"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4842949484681736736"},"published":{"$t":"2014-11-17T19:29:31.885Z"},"updated":{"$t":"2014-11-17T19:29:31.915Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:29:31.885Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"02-frameviewr.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4842949484681736736"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/02-frameviewr.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4842949484681736736"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4842949484681736736"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4842949484681736736"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4842949484681736736"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5959130026653711421"},"published":{"$t":"2014-11-17T19:24:34.718Z"},"updated":{"$t":"2014-11-17T19:24:34.746Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-17T19:24:34.718Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"01-movement.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5959130026653711421"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4583438053064451388"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/rendering-performance-case-study-1/01-movement.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5959130026653711421"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5959130026653711421"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5959130026653711421"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5959130026653711421"}],"author":[{"name":{"$t":"Umar Hansa"},"email":{"$t":"umar.hansa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDUpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4964169974107488744"},"published":{"$t":"2012-10-03T16:54:35.600Z"},"updated":{"$t":"2014-11-12T23:56:19.312Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-12T23:56:18.134Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Disk Layout Format"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eBoards can define their own disk layout, with different partitioning ordering and sizes.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eA board may specify its own layout by placing a layout file in overlay-\u0026lt;board\u0026gt;/scripts/disk_layout.json; if no layout file is found, the default one in scripts/build_library/legacy_disk_layout.json will be used.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eA layout file consists of a \"base\" layout, plus zero or more other types of layout. Common types would be \"usb\" and \"vm\". Each of these layouts is made up of one or more partitions.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe base layout is special, since it's the layout on which all other layouts get overlaid upon. The base layout represents the \"installed\" layout, the way things should be once the image has been installed onto a device. The \"usb\" layout represents how things should look on a USB image (typically, this means that ROOT-B is 1 block long).\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003eSee \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/platform/crosutils/+/HEAD/build_library/README.disk_layout\"\u003ehttps://chromium.googlesource.com/chromiumos/platform/crosutils/+/HEAD/build_library/README.disk_layout\u003c/a\u003e for the exact format details as they may change over time.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003eHere's an example of a partition entry in a layout:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-family:monospace;font-size:small;white-space:pre;background-color:transparent\"\u003e{\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"num\": 5,\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"label\":\"ROOT-B\",\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"type\":\"rootfs\",\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"blocks\":\"4194304\",\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"fs_blocks\":\"217600\"\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e}\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe \"num\" field defines the numerical ID of the partition in the GPT. The \"label\" field defines the name of the partition in the GPT table and also the label of the filesystem if the given partition has a filesystem. The \"blocks\" field defines the number of blocks in size the partition is. Optionally, you can also specify the \"fs_blocks\" field. This defines how large the filesystem on the given partition should be. If you don't specify \"fs_blocks\", the entire partition is used.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe block size for a partition and a filesystem is defined at the top of the layout file, in the metadata section:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e\"metadata\":{\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"block_size\": 512,\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e \"fs_block_size\": 4096\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e},\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:monospace;font-size:small;white-space:pre\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eBoth of these values should be specified in bytes.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont size\u003d\"4\"\u003e\u003cb\u003eFAQ\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eI want to use gmerge and I used to use the --rootfs_size and --rootfs_partition_size options to make my root filesystem larger to aid this, how do I do this now?\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eOpen up legacy_disk_layout.json and edit the ROOT-A/ROOT-B blocks and fs_blocks to your desired sizes, using the block sizes specified at the top of the file. Then copy the values for ROOT-A into the the blocks/fs_blocks for the usb layout. If you want to do this for a VM, copy the values into the vm layout too.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2820759774765985493"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide/disk-layout-format"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4964169974107488744"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4964169974107488744"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4964169974107488744"}],"author":[{"name":{"$t":"Liam McLoughlin"},"email":{"$t":"lmcloughlin@chromium.org"}}],"sites$pageName":{"$t":"disk-layout-format"},"sites$revision":{"$t":"9"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7580098371313439011"},"published":{"$t":"2014-11-12T18:40:49.494Z"},"updated":{"$t":"2014-11-12T18:40:49.532Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-12T18:40:49.494Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"PulseviewSourceCap_request.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7580098371313439011"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/PulseviewSourceCap_request.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7580098371313439011"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7580098371313439011"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7580098371313439011"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7580098371313439011"}],"author":[{"name":{"$t":"Vincent Palatin"},"email":{"$t":"vpalatin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8574738873045956570"},"published":{"$t":"2014-11-12T18:40:46.382Z"},"updated":{"$t":"2014-11-12T18:40:46.427Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-12T18:40:46.382Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"PulseviewRequestAccept.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8574738873045956570"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/PulseviewRequestAccept.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8574738873045956570"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8574738873045956570"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8574738873045956570"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8574738873045956570"}],"author":[{"name":{"$t":"Vincent Palatin"},"email":{"$t":"vpalatin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4186762194439053205"},"published":{"$t":"2014-11-12T16:56:25.067Z"},"updated":{"$t":"2014-11-12T16:56:25.124Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-12T16:56:25.067Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-10-14 10-19-11.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4186762194439053205"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/Screenshot%20from%202014-10-14%2010-19-11.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4186762194439053205"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4186762194439053205"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4186762194439053205"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4186762194439053205"}],"author":[{"name":{"$t":"Bo Liu"},"email":{"$t":"boliu@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4318151372002946369"},"published":{"$t":"2014-11-12T16:54:21.578Z"},"updated":{"$t":"2014-11-12T16:54:21.609Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-12T16:54:21.578Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-10-14 10-18-44.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4318151372002946369"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/Screenshot%20from%202014-10-14%2010-18-44.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4318151372002946369"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4318151372002946369"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4318151372002946369"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4318151372002946369"}],"author":[{"name":{"$t":"Bo Liu"},"email":{"$t":"boliu@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/782421666928319562"},"published":{"$t":"2014-11-12T16:53:09.402Z"},"updated":{"$t":"2014-11-12T16:53:09.431Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-12T16:53:09.402Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-10-14 10-18-30.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/782421666928319562"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/Screenshot%20from%202014-10-14%2010-18-30.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/782421666928319562"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/782421666928319562"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/782421666928319562"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/782421666928319562"}],"author":[{"name":{"$t":"Bo Liu"},"email":{"$t":"boliu@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"WSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3997645127893838801"},"published":{"$t":"2014-03-28T22:59:02.610Z"},"updated":{"$t":"2014-11-06T03:55:58.824Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-06T03:55:57.527Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Dell Chromebook 11"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Specifications\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eSpecifications\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Running-Chromium-OS\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eRunning Chromium OS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disclaimer\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eDisclaimer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-Inside-\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eWhat's Inside?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"http://www.google.com/intl/en/chrome/education/devices/chromebooks.html#d11\"\u003eDell Chromebook 11\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"http://www.chromium.org/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Specifications\" /\u003eSpecifications\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003eCPU: Haswell Celeron 2995U. 1.4GHz, dual-core, 2MB Cache\u003c/li\u003e\r\n\u003cli\u003eRAM: 2GB or 4GB DDR3 (Not upgradeable)\u003c/li\u003e\r\n\u003cli\u003eDisplay: 11.6\" 1366x768\u003c/li\u003e\r\n\u003cli\u003eDisk: 16GB SSD (Not upgradeable)\u003c/li\u003e\r\n\u003cli\u003eI/O:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eHDMI port\u003c/li\u003e\r\n\u003cli\u003e2 x USB 3\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Secure_Digital\" rel\u003d\"nofollow\"\u003eSD slot\u003c/a\u003e (SDXC compatible)\u003c/li\u003e\r\n\u003cli\u003eHeadphone/mic combo jack\u003c/li\u003e\r\n\u003cli\u003eCamera \u0026amp; mic\u003c/li\u003e\r\n\u003cli\u003eKeyboard \u0026amp; touchpad\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eConnectivity:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiFi: 802.11 a/b/g/n\u003c/li\u003e\r\n\u003cli\u003eUSB ports can handle some Ethernet dongles\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eServo header\u003c/a\u003e: Standard 2x25 / AXK750347G\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Kensington_Security_Slot\" rel\u003d\"nofollow\"\u003eKensington Security Slot\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eDetails for working with developer mode can be found \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook\"\u003eon this page\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Running-Chromium-OS\" /\u003eRunning Chromium OS\u003c/h2\u003e\r\n\u003cp\u003eBefore you start fiddling with your own builds it is strongly recommend to create a recovery USB stick or SD card. As long as you don't disable hardware write protect on the system \u0026amp; EC firmware, you can get your machine back into working order by entering Recovery Mode and plugging in your recovery image. You can create a recovery image from Chrome OS by browsing to \u003ca style\u003d\"color:rgb(71,18,100)\"\u003echrome://imageburner\u003c/a\u003e or follow instructions for other OS on the \u003ca href\u003d\"https://support.google.com/chromebook/answer/1080595?hl\u003den\"\u003eChrome OS help center\u003c/a\u003e site.\u003c/p\u003e\r\n\u003cp\u003eYou can build and run Chromium OS on your Dell Chromebook 11 (versions R31 and later). Follow the \u003ca href\u003d\"http://www.chromium.org/chromium-os/quick-start-guide\"\u003equick start guide\u003c/a\u003e to setup a build environment. The board name for Dell Chromebook 11 is \"wolf\". Build an image and write it to a USB stick or SD card.\u003c/p\u003e\r\n\u003cp\u003eTo boot your image you will first need to enable booting developer signed images from USB (or SD card). Switch your machine to Developer mode and get to a shell by either via VT2 (Ctrl+Alt+F2) and logging in as root or by logging in as a user (or guest mode), starting a \"crosh\" shell with Ctrl+Alt+t, and typing \"shell\". Now run \"sudo crossystem dev_boot_usb\u003d1\" and reboot \"sudo reboot\".\u003c/p\u003e\r\n\u003cp\u003ePlug your USB stick or SD card in and on the scary \"OS Verification is OFF\" screen hit Ctrl+u to boot from external media. If all goes well you should see a \"Chromium OS\" logo screen. If you want to install your build to the SSD, open a shell and type \"sudo /usr/sbin/chromeos-install\". Note: This will replace EVERYTHING on your SSD. Use a recovery image if you want to get back to a stock Chrome OS build.\u003c/p\u003e\r\n\u003cp\u003eHave fun!\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-wolf-4389.24.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-wolf-4389.24.B\u003c/code\u003e branches.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Disclaimer\" /\u003eDisclaimer\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to your Chromebook's hardware or software are not supported by Google, may compromise your online \u003c/b\u003e\u003cb\u003esecurity\u003c/b\u003e\u003cb\u003e, and may void your warranty....now on to the fun stuff.\u003c/b\u003e\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-Inside-\" /\u003eWhat's Inside?\u003c/h2\u003e\r\n\u003cp\u003eTaking apart your Chromebook is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center. Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first.\u003c/p\u003e\r\n\u003cp\u003eThe location of the firmware write protection disable screw is indicated by the red arrow below.  Remove the screw, boot the system and run \"flashrom --wp-disable\" to enable writing to the write protected regions of flash.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/dell-chromebook-11/Selection_459.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"231\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1402608307019/chromium-os/developer-information-for-chrome-os-devices/dell-chromebook-11/Selection_459.png\" width\u003d\"320\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/dell-chromebook-11"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3997645127893838801"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3997645127893838801"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3997645127893838801"}],"author":[{"name":{"$t":"Jean Zheng"},"email":{"$t":"jean@chromium.org"}}],"sites$pageName":{"$t":"dell-chromebook-11"},"sites$revision":{"$t":"10"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1216084807215498311"},"published":{"$t":"2014-07-08T19:04:32.652Z"},"updated":{"$t":"2014-11-04T23:33:43.215Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-08T19:10:07.939Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"QUnit.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1216084807215498311"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663636149949114440"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests/QUnit.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1216084807215498311"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1216084807215498311"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1216084807215498311"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1216084807215498311"}],"author":[{"name":{"$t":"Kelvin Poon"},"email":{"$t":"kelvinp@chromium.org"}}],"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2592371718572229913"},"published":{"$t":"2014-07-08T23:10:02.982Z"},"updated":{"$t":"2014-11-04T23:33:43.215Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-08T23:10:02.982Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"EnableCoverage.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2592371718572229913"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663636149949114440"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests/EnableCoverage.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2592371718572229913"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2592371718572229913"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2592371718572229913"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2592371718572229913"}],"author":[{"name":{"$t":"Kelvin Poon"},"email":{"$t":"kelvinp@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3076918073234695193"},"published":{"$t":"2014-07-08T23:12:34.312Z"},"updated":{"$t":"2014-11-04T23:33:43.215Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-08T23:12:34.312Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Coverage.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3076918073234695193"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663636149949114440"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/javascript-unittests/Coverage.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3076918073234695193"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3076918073234695193"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3076918073234695193"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3076918073234695193"}],"author":[{"name":{"$t":"Kelvin Poon"},"email":{"$t":"kelvinp@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3124985333972221545"},"published":{"$t":"2014-10-27T03:35:20.028Z"},"updated":{"$t":"2014-11-04T23:32:05.293Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-27T03:35:20.028Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"menu_check.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3124985333972221545"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5302594218963056229"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/gyp-environment-variables/menu_check.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3124985333972221545"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3124985333972221545"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3124985333972221545"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3124985333972221545"}],"author":[{"name":{"$t":"Sasha Bermeister"},"email":{"$t":"sashab@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6100177934117773234"},"published":{"$t":"2014-09-12T18:22:33.632Z"},"updated":{"$t":"2014-11-04T22:07:33.738Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-04T22:07:32.390Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"libchromeos"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Background\" /\u003eBackground\u003c/h2\u003e\u003cul /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-libchromeos-is-the-utility-library-used-by-most-daemons-in-Chromium-OS-to-share-common-functionality-specific-to-Chromium-OS.-For-more-generic-utility-functions-see-libchrome-utility-library-from-the-Chromium-browser-also-used-by-most-daemons-in-Chromium-O\" /\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003elibchromeos is the utility library used by most daemons in Chromium OS to share common functionality specific to Chromium OS. For more generic utility functions, see \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/libchrome\" style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003elibchrome\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003e, utility library from the Chromium browser, also used by most daemons in Chromium OS.\u003c/span\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eplatform2 projects use C++11 and libchromeos uses some of the new features to simplify and optimize code. For this reason, some generic modules more suitable for libchrome are included in libcrhomeos due to the lack of C++11 support in the former.\u003cdiv\u003e\u003cdiv\u003e\u003cdiv style\u003d\"color:rgb(0,0,0);font-family:Arial,Verdana,sans-serif\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Content-overview\" /\u003eContent overview\u003c/h2\u003e\u003cdiv\u003eThe following is an overview of the current modules of libchromeos. Refer to the latest version of the header files for up to date documentation.\u003c/div\u003e\u003cul /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003eany.h\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eImplementation of chromeos::Any, a native C++ variant type. Any could contain any copy-constructible type.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eExample:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromeos::Any any1 \u003d 5;\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromeos::Any any2 \u003d true;\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eint v1 \u003d any1.Get\u0026lt;int\u0026gt;();\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003ebool v2 \u003d any2.Get\u0026lt;bool\u0026gt;();\u003c/font\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003ebind_lambda.h\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eBind adapter for C++ functor objects, including lambdas:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003ebase::Callback\u0026lt;int(int, int)\u0026gt; callback_add \u003d base::Bind([](int a, int b) { return a + b;});\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eLOG(INFO) \u0026lt;\u0026lt; \"2+2\u003d\" \u0026lt;\u0026lt; callback_add.Run(2, 2);\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003edata_encoding.h\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eUtility functions to encode/decode URLs and web-form-like parameters.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003estd::string encoded \u003d WebParamsEncode({{\"q\", \"test\"}, {\"path\", \"/usr/bin\"}, {\"#\", \"%\"}});\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eEXPECT_EQ(\"q\u003dtest\u0026amp;path\u003d%2Fusr%2Fbin\u0026amp;%23\u003d%25\", encoded);\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003edbus/*\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eA whole lot of useful utility functions and classes to help build native D-Bus clients and servers. Helper functions to dispatch D-Bus method calls to remote object as if they were native C++ functions:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eauto response \u003d chromeos::dbus_utils::\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003eCallMethodAndBlock(object_proxy, \"org.chromium.MyService.MyInterface\", \"MyMethod\", 2, 8.7);\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromeos::ErrorPtr error;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003estd::string return_value;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eif (ExtractMethodCallResults(\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003eresponse\u003c/span\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e, \u0026amp;error, \u0026amp;return_value)) {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  // Use the |return_value|.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e} else {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  // An error occurred. Use |error| to get details.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003eerrors/error.h\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eError class that provides rich error reporting facilities. Each error object contains an error domain, error code and error message. Errors can be nested to provide additional error context.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e \u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003evoid foo(ErrorPtr* error) {\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Error::AddTo(error, \"my_domain\", \"not_supported\", \"function not supported\");\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cdiv\u003e\u003cb\u003eflag_helper.h\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003eCommand line flag handling class that exposes an API similar to that of gflags, using base/command_line.h as the actual parser.  Flags are defined from within main(..) using macros, then once initialized can be referenced by FLAGS_name variables.  Unlike with gflags, however, these variables are scoped to within main(...).  All the DEFINE_type macros take three arguments: the flag name, the default value, and the help text.  The types of flags supported are: bool, int32, int64, uint64, double, and string.  The FlagHelper class automatically handles generation of '--help' output, as well as exiting the program in the case of incorrect flag parsing, such as passing a string to an int flag.\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e#include \u0026lt;chromeos/flag_helper.h\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e#include \u0026lt;stdio.h\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003eint main(int argc, char** argv) {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e  DEFINE_int32(example, 0, \"Example int flag\");\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e  chromeos::FlagHelper::Init(argc, argv, \"Test application.\");\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e  printf(\"You passed in %d to --example command line flag\\n\",\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e         FLAGS_example);\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e  return 0;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003ehttp/http_utils.h\u003c/b\u003e (and \u003cb\u003ehttp/*\u003c/b\u003e)\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eA bunch of functionality to make http requests (currently built on top of libcurl).\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromeos::http::HeaderList headers \u003d {{\"X-Chrome-UMA-Log-SHA1\", hash}};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromeos::ErrorPtr error;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eauto response \u003d chromeos::http::PostText(\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    \"\u003ca href\u003d\"http://server.com/url\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003ehttp://server.com/url\u003c/a\u003e\",\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    \"text data to post\",\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    chromeos::mime::text::kPlain, headers, chromeos::http::Transport::CreateDefault(), \u0026amp;error);\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eif (!response || response-\u0026gt;GetDataAsString() !\u003d \"OK\") {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  LOG(ERROR) \u0026lt;\u0026lt; \"Failed to send data: \" \u0026lt;\u0026lt; error-\u0026gt;GetMessage();\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003emap_utils.h\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eTemplate helper functions for std::map. You can get a list of keys or values out of a map:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003estd::map\u0026lt;string, string\u0026gt; map \u003d ....\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003estd::vector\u0026lt;string\u0026gt; keys \u003d chromeos::GetMapKeys(map);\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003estd::vector\u0026lt;string\u0026gt; values \u003d chromeos::GetMapValues(map);\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003emime_utils.h\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eUtility functions to compose, parse, and manipulate MIME strings. Also contains lots of predefined constants for common mime types. So you should never have to hardcode \"text/html\" in \u003cspan style\u003d\"background:rgb(255,255,204)\"\u003eyour\u003c/span\u003e code.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eEXPECT_EQ(mime::text::kPlain, mime::RemoveParameters(\"text/plain;charset\u003dutf8\"));\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003estrings/string_utils.h\u003c/b\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eHelper string functions in addition to those provided by base/strings. Mostly for splitting/joining.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003estd::string input \u003d \"abc;def;ghi\";\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003efor (const std::string\u0026amp; token : chromeos::string_utils::Split(input, ';')) {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  // process each token\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cb\u003eurl_utils.h\u003c/b\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eFunctions to split, combine and manipulate URLs\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eEXPECT_EQ(\"\u003ca href\u003d\"http://sample.org/obj/part1/part2\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003ehttp://sample.org/obj/part1/part2\u003c/a\u003e\", url::CombineMultiple(\"\u003ca href\u003d\"http://sample.org/\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003ehttp://sample.org\u003c/a\u003e\", {\"obj\", \"part1\", \"part2\"}));\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7575192847733958161"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/libchromeos"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6100177934117773234"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6100177934117773234"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6100177934117773234"}],"author":[{"name":{"$t":"Alex Deymo"},"email":{"$t":"deymo@chromium.org"}}],"sites$pageName":{"$t":"libchromeos"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/34398978325576475"},"published":{"$t":"2014-11-03T04:16:58.947Z"},"updated":{"$t":"2014-11-03T04:17:24.478Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-11-03T04:17:22.922Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Gclient Managed Mode"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif\"\u003eManaged mode is a \u003cb\u003edeprecated\u003c/b\u003e feature of gclient. It was conceived to give an easier workflow for newcomers to git, but turned out to be full of surprising behaviors. It has thus been deprecated, unmanaged mode is the default, and existing users of managed mode are encouraged to change to unmanaged mode.\u003c/p\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif\"\u003eTo check which mode you are using, check \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003e.gclient\u003c/tt\u003e (the gclient config file) and see the value of the \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003e\"managed\"\u003c/tt\u003e flag. To switch to unmanaged mode from managed mode:\u003c/p\u003e\u003cul style\u003d\"padding-left:25px;max-width:62em;font-family:arial,sans-serif\"\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eedit your \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003e.gclient\u003c/tt\u003e and set:\u003c/li\u003e\u003cpre style\u003d\"font-size:12px;padding:0.5em;overflow:auto;font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;max-width:70em;background-color:rgb(238,238,238)\"\u003e   \u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"managed\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e:\u003c/span\u003e \u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eFalse\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e,\u003c/span\u003e\u003c/pre\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eupdate your repository by using \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egit pull\u003c/tt\u003e (as described above), followed by \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egclient sync\u003c/tt\u003e, rather than just \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egclient sync\u003c/tt\u003e.\u003c/li\u003e\u003c/ul\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif\"\u003eTo make the Blink repo also unmanaged, first \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003efetch blink\u003c/tt\u003e and then:\u003c/p\u003e\u003cul style\u003d\"padding-left:25px;max-width:62em;font-family:arial,sans-serif\"\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eedit your \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003e.gclient\u003c/tt\u003e and set:\u003c/li\u003e\u003cpre style\u003d\"font-size:12px;padding:0.5em;overflow:auto;font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;max-width:70em;background-color:rgb(238,238,238)\"\u003e   \u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"managed\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e:\u003c/span\u003e \u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eFalse\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e,\u003c/span\u003e\u003cbr /\u003e   \u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"custom_deps\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e:\u003c/span\u003e \u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e{\u003c/span\u003e\u003cbr /\u003e      \u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"src/third_party/WebKit\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e:\u003c/span\u003e \u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eNone\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e,\u003c/span\u003e\u003cbr /\u003e   \u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e},\u003c/span\u003e\u003c/pre\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eupdate your repository by using \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egit pull\u003c/tt\u003e in Chromium, then \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egit pull\u003c/tt\u003e in Blink (as described above), followed by \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egclient sync\u003c/tt\u003e, rather than just \u003ctt style\u003d\"font-family:Monaco,DejaVu Sans Mono,Bitstream Vera Sans Mono,Lucida Console,monospace;font-size:12px;max-width:66em\"\u003egclient sync\u003c/tt\u003e.\u003c/li\u003e\u003c/ul\u003e\u003ch2 style\u003d\"font-size:large;border:0px;padding-left:0px;max-width:700px;font-family:arial,sans-serif;background-image:none\"\u003e\u003ca name\u003d\"Reference\" /\u003eReference\u003c/h2\u003e\u003cul style\u003d\"padding-left:25px;max-width:62em;font-family:arial,sans-serif\"\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003e“\u003ca href\u003d\"https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/n9N5N3JL2_U\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ePSA: fetch chromium now uses git unmanaged mode\u003c/a\u003e”\u003c/li\u003e\u003c/ul\u003e\u003cp style\u003d\"line-height:1.25em;max-width:64em;font-family:arial,sans-serif\"\u003eThe main difference between managed mode and unmanaged mode is that in managed mode, local branches track local master branch instead of origin/master, and gclient “manages” the branches so that they stay in sync. However in practice this leads to two master branches (local master and origin/master) that go out of sync and prevent further uploads/commits. With unmanaged mode you always have only one master: origin/master. The local master still exists but is not treated in any special way by the tools.\u003c/p\u003e\u003ch2 style\u003d\"font-size:large;border:0px;padding-left:0px;max-width:700px;font-family:arial,sans-serif;background-image:none\"\u003e\u003ca name\u003d\"What's_missing\" /\u003eWhat's missing\u003c/h2\u003e\u003cul style\u003d\"padding-left:25px;max-width:62em;font-family:arial,sans-serif\"\u003e\u003cli style\u003d\"margin-bottom:0.3em\"\u003eSafesync is not supported for new managed git checkouts yet (\u003ca href\u003d\"http://crbug.com/109191\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ehttp://crbug.com/109191\u003c/a\u003e).\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7768323185310599139"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code/gclient-managed-mode"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/34398978325576475"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/34398978325576475"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/34398978325576475"}],"author":[{"name":{"$t":"Sasha Bermeister"},"email":{"$t":"sashab@chromium.org"}}],"sites$pageName":{"$t":"gclient-managed-mode"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3401651446744760216"},"published":{"$t":"2014-10-30T18:21:10.200Z"},"updated":{"$t":"2014-10-30T18:21:10.229Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-30T18:21:10.200Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Twinkie-diagram.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3401651446744760216"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/Twinkie-diagram.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3401651446744760216"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3401651446744760216"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3401651446744760216"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3401651446744760216"}],"author":[{"name":{"$t":"Vincent Palatin"},"email":{"$t":"vpalatin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2487943522186295908"},"published":{"$t":"2014-10-30T17:50:11.114Z"},"updated":{"$t":"2014-10-30T17:50:11.154Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-30T17:50:11.114Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"twinkies-2.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2487943522186295908"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/twinkies-2.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2487943522186295908"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2487943522186295908"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2487943522186295908"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2487943522186295908"}],"author":[{"name":{"$t":"Vincent Palatin"},"email":{"$t":"vpalatin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9068068568535931733"},"published":{"$t":"2014-10-30T17:50:09.016Z"},"updated":{"$t":"2014-10-30T17:50:09.042Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-30T17:50:09.016Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"twinkies-1.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/9068068568535931733"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/twinkies-1.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9068068568535931733"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9068068568535931733"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9068068568535931733"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/9068068568535931733"}],"author":[{"name":{"$t":"Vincent Palatin"},"email":{"$t":"vpalatin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5284731191849591482"},"published":{"$t":"2014-10-30T17:50:06.878Z"},"updated":{"$t":"2014-10-30T17:50:06.917Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-30T17:50:06.878Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"twinkies-3.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5284731191849591482"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9043492987541181918"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/twinkie/twinkies-3.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5284731191849591482"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5284731191849591482"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5284731191849591482"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5284731191849591482"}],"author":[{"name":{"$t":"Vincent Palatin"},"email":{"$t":"vpalatin@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1517603650516152928"},"published":{"$t":"2014-10-29T15:49:47.240Z"},"updated":{"$t":"2014-10-29T15:49:47.293Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-29T15:49:47.240Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Chrome Security Architecture.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1517603650516152928"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/331306076570816221"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/guts/Chrome%20Security%20Architecture.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1517603650516152928"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1517603650516152928"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1517603650516152928"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1517603650516152928"}],"author":[{"name":{"$t":"Parisa Tabriz"},"email":{"$t":"parisa@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDspeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/358576904228918905"},"published":{"$t":"2014-10-20T17:06:59.139Z"},"updated":{"$t":"2014-10-22T21:02:59.695Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-22T21:02:58.118Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Optimizing Energy Consumption"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003ch1 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Background-Info\" /\u003e\u003cspan style\u003d\"font-size:21px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eBackground Info\u003c/font\u003e\u003c/span\u003e\u003c/h1\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eHere are two really great talks on optimizing battery life:\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMac:\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e \u003c/span\u003e\u003ca href\u003d\"https://developer.apple.com/videos/wwdc/2013/#701\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMaximizing Battery Life on OS X, WWDC 2013\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e is a great overview.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAndroid\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, \u003c/span\u003e\u003ca href\u003d\"https://www.youtube.com/watch?v\u003dKzSKIpJepUw\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eproject volta\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e talk. (Google-internal \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/google.com/volta/\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eproject volta\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e \u003c/span\u003e\u003ca href\u003d\"http://go/volta-tech-talk-video\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etech talk\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e and \u003c/span\u003e\u003ca href\u003d\"http://go/volta-tech-talk\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eslides\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e)\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch1 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Telemetry-tests\" /\u003e\u003cspan style\u003d\"font-size:21px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eTelemetry tests\u003c/font\u003e\u003c/span\u003e\u003c/h1\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWe use Telemetry benchmarks for testing and analyzing energy usage. See \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/developers/telemetry#TOC-Code-Concepts\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ecode concepts\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e for details on benchmarks, measurements, and page sets.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Measurements\" /\u003e\u003cspan style\u003d\"font-size:17px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eMeasurements\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eOn \u003c/span\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003edesktop\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, the \u003c/span\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etab_switching\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e measurement opens a group of tabs and measures energy after they are all loaded. All except the last tab are backgrounded. You can use the benchmark with a blank page in the foreground to understand how background tabs behave, or with a regular page in the foreground to focus on the foreground tab.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eOn \u003c/span\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eandroid\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, our chromium.perf tests and most of our development is on chrome shell, which does not support tabs. So we use the \u003c/span\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003epower\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e test instead. It will load each page in the set, with a 20 second pause, a scroll, and another 20 second pause in between each load.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Page-sets\" /\u003e\u003cspan style\u003d\"font-size:17px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ePage sets\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIt might be a good idea to \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/developers/telemetry/record_a_page_set\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003erecord a custom page set\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e if you’re working on a very specific issue, for example below-the-fold animated gif. But we generally use the below page sets for most of our testing and debugging:\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eDesktop:\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/page_sets/typical_25.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);font-weight:bold;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etypical_25\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - This is a set of 25 web pages designed to represent general web browsing.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/page_sets/top_10.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);font-weight:bold;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etop_10\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e \u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- The Alexa top 10 sites.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/page_sets/top_10_mobile.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);font-weight:bold;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etop_10_mobile\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - Mobile versions of the Alexa top 10\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/page_sets/five_blank_pages.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);font-weight:bold;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003efive_blank_pages\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - For debugging background noise that occurs regardless of which page you’re on. \u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/page_sets/tough_energy_cases.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);font-weight:bold;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etough_energy_cases\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - Very complex or energy-heavy pages.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eAndroid:\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-weight:bold;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/perf/page_sets/typical_10_mobile.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etypical_10_mobile\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - 10 typical mobile pages.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Metrics\" /\u003e\u003cspan style\u003d\"font-size:17px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eMetrics\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eEach platform has different techniques for measuring energy usage, and often there are multiple techniques (hardware devices, software estimation). Below are the names of the metrics, the platforms they are available on, and how they are gathered.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenergy_consumption_mwh\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - This is the energy consumption in milliwatt hours. In general, this is a software estimation. You can see all the methods we have for measuring energy consumption in the \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/telemetry/telemetry/core/platform/power_monitor/\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003epower_monitor\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e directory in telemetry, but here is a quick run-down of how the bots on the waterfall calculate this:\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAndroid uses \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor.py\u0026amp;q\u003ddumpsys\u0026amp;sq\u003dpackage:chromium\u0026amp;l\u003d12\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003edumpsys\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e software estimation on L release and above.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eExcept Nexus 10, which uses the built in \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/telemetry/telemetry/core/platform/power_monitor/android_ds2784_power_monitor.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eds2784\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e fuel gauge on L release and above.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMac OS uses \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003epowermetrics\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e on 10.9 and above (\u003c/span\u003e\u003ca href\u003d\"https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/powermetrics.1.html\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003emore details here\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e).\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWindows and Linux use \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/tools/telemetry/telemetry/core/platform/power_monitor/msr_power_monitor.py\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMSR\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e on intel processors with sandybridge or later.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eapplication_energy_consumption_mwh\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - This is derived by measuring energy_consumption_mwh during a quiescent period before running chrome, then subtracting that from the energy_consumption_mwh used during the test run. The goal is to find the amount of energy used by chrome and ignore the steady state energy used by the OS and background processes. However, if there is too much noise this number can be off.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eidle_wakeups_total\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - This is the total number of idle wakeups across all processes. It’s currently only available on Mac through powermetrics, but we are working on Linux (bug \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/422170\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e422170\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e) and Android (bug \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/422967\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e422967\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e).\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis number is important because it’s a proxy for energy consumption, and it figures heavily in the \u003c/span\u003e\u003ca href\u003d\"http://support.apple.com/kb/HT5873\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eEnergy Impact\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e score in OS X. See the \u003c/span\u003e\u003ca href\u003d\"https://developer.apple.com/videos/wwdc/2013/#701\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMaximizing Battery Life on OS X\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e talk for more info about how reducing idle wakeups improves battery life.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eboard_temperature\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e - Temperature in degrees celsius. Available through MSR on Windows/Linux (intel sandybridge and later). Also available on Android devices running L release+.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;line-height:17.25px;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003ch1 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Developing-Testing-Locally\" /\u003e\u003cspan style\u003d\"font-size:21px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eDeveloping/Testing Locally\u003c/font\u003e\u003c/span\u003e\u003c/h1\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eChoose or record a telemetry page set that matches the use case you want to test.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eRun the correct telemetry benchmark for your platform (tab_switching for desktop, acceptance test for android). Use the --profiler\u003dtrace and --pageset-repeat\u003d1 flags; this will output a trace and only repeat the test once. Example:\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etools/perf/run_benchmark tab_switching.five_blank_pages \\\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e    --browser\u003drelease --profiler\u003dtrace --pageset-repeat\u003d1\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eTelemetry outputs a trace file. You’ll see the file name in stdout. Open it up in \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/developers/how-tos/trace-event-profiling-tool\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eabout:tracing\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. Look for places where:\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003c/li\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:lower-alpha;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eChrome is doing unexpected work. For example, a timer that wakes every 1s on a blank page should not be needed. Removing unneeded timers is a great way to reduce idle wakups.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:lower-alpha;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eWork is happening too frequently and could be coalesced. Could two IPCs be grouped into one? Doing the same amount of work with fewer IPCs reduces idle wakeups.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eComparing traces between two builds that have different energy usage can also be helpful. You can use the --browser argument in telemetry to easily run the test on your stable, beta, or dev channel and compare that with a local build (--browser\u003drelease or --browser\u003ddebug).\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch1 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Verifying-Results-on-Perf-Bots\" /\u003e\u003cspan style\u003d\"font-size:21px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eVerifying Results on Perf Bots\u003c/font\u003e\u003c/span\u003e\u003c/h1\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eEnergy measurements are very sensitive to noise. Sometimes you make a change locally that drives down idle wakeups and you believe will reduce energy consumption, but the energy numbers you get are just noise. Sometimes you don’t have access to the OS or hardware you want to test. The chromium.perf and tryserver.chromium.perf bots can help!\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ePerf Try Jobs\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eYou can run tab_switching tests on the perf trybots on the \u003c/span\u003e\u003ca href\u003d\"http://build.chromium.org/p/tryserver.chromium.perf/waterfall\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etryserver.chromium.perf waterfall\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. Here is the \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/developers/performance-try-bots\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003edocumentation for perf try jobs\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. If idle wakeups numbers are available, they will be in the “memory” tab of the results html page.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003echromium.perf waterfall\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eSeveral energy tests are running on the chromium.perf waterfall:\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"https://chromeperf.appspot.com/report?masters\u003dChromiumPerf\u0026amp;bots\u003dchromium-rel-mac9%2Cchromium-rel-win7-dual%2Cchromium-rel-win7-gpu-ati%2Cchromium-rel-win7-gpu-intel%2Cchromium-rel-win7-gpu-nvidia%2Cchromium-rel-win7-single%2Cchromium-rel-win7-x64-dual%2Cchromium-rel-win8-dual%2Cchromium-rel-xp-dual%2Clinux-oilpan-release%2Clinux-release\u0026amp;tests\u003dtab_switching.five_blank_pages%2Fenergy_consumption_mwh\u0026amp;rev\u003d299488\u0026amp;checked\u003denergy_consumption_mwh%2Cblank_page.html_ref%2Cref%2Cenergy_consumption_mwh%2Cblank_page.html_ref%2Cref\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003etab_switching.five_blank_pages\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"https://chromeperf.appspot.com/report?masters\u003dChromiumPerf\u0026amp;bots\u003dchromium-rel-mac9%2Cchromium-rel-win7-dual%2Cchromium-rel-win7-gpu-ati%2Cchromium-rel-win7-gpu-intel%2Cchromium-rel-win7-gpu-nvidia%2Cchromium-rel-win7-single%2Cchromium-rel-win7-x64-dual%2Cchromium-rel-win8-dual%2Cchromium-rel-xp-dual%2Clinux-oilpan-release%2Clinux-release\u0026amp;tests\u003dtab_switching.top_10%2Fenergy_consumption_mwh\u0026amp;rev\u003d299488\u0026amp;checked\u003denergy_consumption_mwh%2Cref\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003etab_switching.top_10\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"https://chromeperf.appspot.com/report?masters\u003dChromiumPerf\u0026amp;bots\u003dchromium-rel-mac9%2Cchromium-rel-win7-dual%2Cchromium-rel-win7-gpu-ati%2Cchromium-rel-win7-gpu-intel%2Cchromium-rel-win7-gpu-nvidia%2Cchromium-rel-win7-single%2Cchromium-rel-win7-x64-dual%2Cchromium-rel-win8-dual%2Cchromium-rel-xp-dual%2Clinux-oilpan-release%2Clinux-release\u0026amp;tests\u003dtab_switching.typical_25%2Fenergy_consumption_mwh\u0026amp;rev\u003d299488\u0026amp;checked\u003denergy_consumption_mwh%2Cref%2Cenergy_consumption_mwh%2Cref\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003etab_switching.typical_25\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"https://chromeperf.appspot.com/report?masters\u003dChromiumPerf\u0026amp;bots\u003dchromium-rel-mac9%2Cchromium-rel-win7-dual%2Cchromium-rel-win7-gpu-ati%2Cchromium-rel-win7-gpu-intel%2Cchromium-rel-win7-gpu-nvidia%2Cchromium-rel-win7-single%2Cchromium-rel-win7-x64-dual%2Cchromium-rel-win8-dual%2Cchromium-rel-xp-dual%2Clinux-oilpan-release%2Clinux-release\u0026amp;tests\u003dtab_switching.tough_energy_cases%2Fenergy_consumption_mwh\u0026amp;rev\u003d299488\u0026amp;checked\u003denergy_consumption_mwh%2Cref%2Cenergy_consumption_mwh%2Cref\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003etab_switching.tough_energy_cases\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"https://chromeperf.appspot.com/report?masters\u003dChromiumPerf\u0026amp;bots\u003dandroid-motoe%2Candroid-nexus10%2Candroid-nexus4%2Candroid-nexus5%2Candroid-nexus7v2\u0026amp;tests\u003dpower.android_acceptance%2Fenergy_consumption_mwh\u0026amp;checked\u003dcore\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003epower.android_acceptance\u003c/font\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eYou can look at the effects of a submitted change. After \u003c/span\u003e\u003ca href\u003d\"http://crbug.com/423394\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ebug 423394\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e is fixed, you will be able to get traces for some of the runs as well.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2433140667124192106"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/optimizing-energy-consumption"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/358576904228918905"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/358576904228918905"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/358576904228918905"}],"author":[{"name":{"$t":"Annie Sullivan"},"email":{"$t":"sullivan@chromium.org"}}],"sites$pageName":{"$t":"optimizing-energy-consumption"},"sites$revision":{"$t":"7"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6912185240818853607"},"published":{"$t":"2013-04-26T07:42:14.274Z"},"updated":{"$t":"2014-10-17T15:44:04.815Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-17T15:44:02.055Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"V8 Bindings, Promises"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://docs.google.com/a/chromium.org/document/d/1WphFrSM18-m6b4RFaBxwLL_zNlpOdCtEbuRclQ-S_ts/edit#\" style\u003d\"font-size:10pt;background-color:transparent\"\u003ePromise helpers design doc\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2023764670965291136"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/blink/v8-bindings"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6912185240818853607"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6912185240818853607"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6912185240818853607"}],"author":[{"name":{"$t":"Jochen Eisinger"},"email":{"$t":"jochen@chromium.org"}}],"sites$pageName":{"$t":"v8-bindings"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"WSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2260845138845475075"},"published":{"$t":"2014-06-26T16:52:10.822Z"},"updated":{"$t":"2014-10-17T12:05:26.911Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-17T12:05:25.389Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Advanced Integration for SAML SSO on Chrome Devices"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis page describes the advanced integration that \u003cb\u003emay\u003c/b\u003e be done in enabling SAML SSO on Chrome Devices. This article is intended for partners, SAML SSO vendors and IT administrators. The integration described in this document is not mandatory for the feature to work. For basic information on how SAML SSO can be enabled for Chrome Devices, please refer to \u003ca href\u003d\"https://support.google.com/chrome/a/answer/6060880\" target\u003d\"_blank\"\u003ethis article\u003c/a\u003e.\u003c/span\u003e\u003c/span\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Chrome-Credentials-Passing-API\" /\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"4\"\u003eChrome Credentials Passing API\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAPI version 1.0 - 3rd June 2014\u003c/span\u003e\u003c/p\u003e\u003cdiv /\u003e\u003c/span\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Motivation\" /\u003e\u003cfont size\u003d\"4\"\u003eMotivation\u003cbr /\u003e\u003c/font\u003e\u003c/h4\u003e\u003cspan style\u003d\"background-color:transparent;font-family:Arial;font-size:15px;white-space:pre-wrap;line-height:1.15;font-weight:normal\"\u003eUsers can sign in to Chrome with their Google accounts. The password is verified by Google’s authentication servers but is also used locally in Chrome to provide features such as session lock/unlock, Chrome Device offline sign-in and Chrome Device user data encryption. For SAML users, authentication is performed by a third-party identity provider (IdP). This document describes an API that SAML IdPs can use to securely provide Chrome with the user credentials required to implement the session lock/unlock, offline sign-in, and data encryption features.\u003c/span\u003e\u003cspan\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Overview\" /\u003e\u003cspan style\u003d\"vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cfont size\u003d\"4\"\u003e\u003cspan style\u003d\"vertical-align:baseline\"\u003eOverview\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/h4\u003e\u003cspan style\u003d\"vertical-align:baseline\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:normal;line-height:1.15;white-space:pre-wrap\"\u003eThe Chrome sign-in flow is entirely web-based. Google’s authentication service redirects to the IdP, the IdP guides the user through the authentication process and eventually redirects back to a Google URL, reporting success or failure (see the \u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003ca href\u003d\"https://developers.google.com/google-apps/sso/saml_reference_implementation\" style\u003d\"line-height:1.15;background-color:transparent;font-size:10pt;font-weight:normal;text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003eGoogle developer documentation\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"line-height:1.15;background-color:transparent;font-weight:normal;font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e). The IdP’s authentication flow typically consists of at least three steps:\u003c/span\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ean HTML login form collects user credentials\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ethe IdP verifies that the credentials submitted are correct\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ean HTML page performs the redirect to the Google URL, indicating success/failure\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis document introduces a JavaScript API via which the IdP can pass user credentials to Chrome in step 1 and can inform Chrome when the credentials have been verified in step 3. The API works locally: API methods are called by a script that is executed by Chrome as part of the SAML IdP’s web-based authentication flow and are processed by the same instance of Chrome. They do not flow through any server. The API methods are provided by a JavaScript file that handles the lower-level communication with Chrome. This file is hosted by Google at:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca href\u003d\"https://ssl.gstatic.com/accounts/chrome/users-1.0.js\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://ssl.gstatic.com/accounts/chrome/users-1.0.js\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe recommend that SAML IdPs reference this file at the above location in their scripts. This way, any improvements and bug fixes to the file will be picked up automatically. We will make every effort to keep the API provided by this file stable.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Key-Types\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"4\"\u003eKey Types\u003c/font\u003e\u003c/span\u003e\u003c/h4\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTo support session lock/unlock, offline sign-in and user data encryption, Chrome must be able to authenticate a returning user without contacting any servers. This is done by deriving a key from the user’s password via a one-way hash function during initial authentication. When the user returns and enters his/her password again, the same one-way hash function is applied to this password. If the resulting keys match, the password entered was correct and the user is authenticated.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eChrome uses a built-in one-way hash function to derive keys from passwords for non-SAML users. The same one-way hash function is used when a SAML IdP passes a user’s password to Chrome via the API described in this document. Chrome discards the password after hashing and does not store it anywhere. An alternative is for the IdP to apply a one-way hash function and pass the derived key to Chrome. When the user returns and enters his/her password, Chrome must apply the same one-way hash function to determine whether the password entered is correct. The IdP must therefore use a one-way hash function supported by Chrome and must also pass Chrome any additional metadata required to repeat the hashing, such as a salt.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eChrome provides the SAML IdP with a list of supported key derivation mechanisms when the IdP initializes the API. \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eKEY_TYPE_PASSWORD_PLAIN\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is always supported. For this key type, the IdP passes the password to Chrome and Chrome applies its built-in one-way hash function to it. Additional key types, in which the IdP applies a one-way hash function and passes the key and metadata to Chrome, will be added in the future.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003cspan\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-API-Methods\" /\u003e\u003cbr /\u003e\u003cfont size\u003d\"4\"\u003eAPI Methods\u003cbr /\u003e\u003c/font\u003e\u003c/h4\u003e\u003cspan style\u003d\"line-height:1.15;background-color:transparent;font-family:Arial;font-size:15px;white-space:pre-wrap;font-weight:normal\"\u003eThe API consists of three JavaScript methods:\u003c/span\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-family:Consolas;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize(callback)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-family:Consolas;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd(details, callback)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-family:Consolas;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete(details, callback)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAll methods are asynchronous. Each method will invoke the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e passed to it when its work is done. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method must be called first to initialize the API. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method is then used to pass credentials to Chrome and the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method is used to inform Chrome that the passed credentials have been verified. IdP login flows typically span multiple HTML login pages. The API supports this by allowing its methods to be called from different pages.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHowever, the API must correlate the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call that indicates authentication success with the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call that passed the corresponding credentials. This correlation is established using the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e argument: The SAML IdP passes a \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e of its choosing in the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edetails\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e provided to the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call and must then pass the same \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e in the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edetails\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e of the corresponding \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call. The API uses the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e to correlate these method calls only. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is treated as opaque, is not interpreted in any way and is discarded at the end of the sign-in process.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf authentication fails, Chrome may return to the sign-in form, asking the user to try signing in again. A sign-in process can thus encompass multiple authentication attempts. To ensure that method calls are correlated correctly, the SAML IdP should use a different \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e for each of these authentication attempts. \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe IdP must then choose a \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e when calling \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e and must keep this token as part of its internal state until \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e is called. The need to generate and keep track of a suitable \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e can be avoided by using the \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e (see the \u003c/span\u003e\u003ca href\u003d\"https://developers.google.com/google-apps/sso/saml_reference_implementation\" style\u003d\"line-height:1.15;font-size:10pt;text-decoration:none;background-color:transparent\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003eGoogle SAML developer documentation\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e for a definition) as the \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. The \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e meets all requirements that the \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;font-size:10pt;font-family:Consolas;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e must fulfill:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:13px;font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e remains constant throughout an authentication attempt\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:13px;font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is different for each authentication attempt\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:13px;font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e must be passed through from the start to the end of the authentication flow so that it will be available in steps 1 and 3 of the flow\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhile the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is an obvious choice for the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, a SAML IdP is free to choose any other \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e instead, as long as it allows the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e and \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e calls to be correlated.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cspan\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-initialize-callback-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize(callback)\u003c/span\u003e\u003c/h2\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method should be invoked once at the start of the authentication flow. While the API is currently implemented by Chrome only, a SAML IdP is not required to (and should not) interpret the user agent string to determine whether the API is available or not. Instead, the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method should always be called at the start of the authentication flow, regardless of user agent.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf the authentication attempt is part of a sign-in process on a version of Chrome that provides the API, Chrome will invoke the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e with a list of supported key types. Once the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e has been invoked by Chrome, the IdP may use the API by calling the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e and \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e methods.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn all other cases (e.g., not Chrome, older version of Chrome, not part of the sign-in process), the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e will not be invoked. If the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is not invoked, the API is not available and the IdP must not call any of its other methods. If the IdP’s authentication flow spans multiple HTML pages, the IdP must keep track of the initialization result across these pages. If the API is available, the IdP should call the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e and \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e methods at the appropriate points in the authentication flow. Otherwise, the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e and \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e methods must not be called.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e should be a function that takes a single argument, \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ekeyTypes\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e. Chrome passes an array of string constants indicating the supported key derivation mechanisms via this argument (see the key types section \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003efor details). The constant \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e’KEY_TYPE_PASSWORD_PLAIN’\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e will always be present in this array. Additional constants indicating further key derivation mechanisms will be added in the future.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-add-details-callback-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd(details, callback)\u003c/span\u003e\u003c/h2\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis method should be invoked when the user has finished entering his/her credentials. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edetails\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e should be a JavaScript object that contains the following fields:\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003euser\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003epasswordBytes\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ekeyType\u003c/span\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is used to correlate the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call with a subsequent \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call. It is not interpreted by the API in any way and may be freely chosen by the IdP (see the API methods section \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003efor details). The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003euser\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e field should be set to the user’s e-mail address. If the IdP does not know the user’s e-mail address, an empty string should be passed.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe next two fields are used to pass a key to Chrome. \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ekeyType\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e indicates the key derivation mechanism that the IdP used to derive the key from the user’s password. It must be one of the string constants that the API returned in the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ekeyTypes\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e array during initialization (see the previous section \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003efor details). \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003epasswordBytes\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e contains the key and any metadata required to repeat the hashing process that was used to derive the key.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhen the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ekeyType\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e’KEY_TYPE_PASSWORD_PLAIN’\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003epasswordBytes\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e contains the password itself. For other key types that will be added in the future, \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003epasswordBytes\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e will contain the metadata, such as a salt, and the key, separated by a delimiter.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e will be invoked when Chrome has received the credentials. Since the user has not been authenticated yet, Chrome keeps the credentials in memory only and does not store them permanently until the corresponding \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method is called.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method will typically be called when the HTML login form is about to submitted. It is important to not actually submit the form until after the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e has been invoked. If the IdP calls the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method and submits the form without waiting for the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, the HTML page containing the login form and any scripts it is running it will be torn down immediately, preventing the credentials from reaching Chrome. The recommended way to handle form submission is to set the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e to \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eform.submit.bind(form)\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, where \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eform\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is the DOM node representing the login form. This way, the form will be submitted automatically when Chrome has received the credentials and invokes the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf the credentials entered are incorrect, the IdP will typically end the authentication flow with a \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSAMLResponse\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e indicating failure. However, an IdP may also redirect back to the IdP’s login form, allowing the user to try entering his/her credentials again. If the IdP implements this flow, the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method should be called whenever new credentials are entered. It is permissible to reuse the same \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e in this case. When the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method is called with new credentials, any credentials previously passed with the same \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e are superseded and replaced.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-complete-details-callback-\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete(details, callback)\u003c/span\u003e\u003c/h2\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method should be invoked when the user’s credentials have been verified by the SAML IdP and the user is authenticated. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edetails\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e should be a JavaScript object that contains one field, \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etoken\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e must match the one that was passed to the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call for this authentication attempt, allowing the two calls to be correlated. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call indicates that the credentials which the IdP had passed to the corresponding \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eadd\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e call are valid. Chrome will use these credentials to provide the session lock/unlock, offline sign-in, and data encryption features for this user. The \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e will be invoked when Chrome has processed the credentials and has stored them permanently.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAfter verifying the user’s credentials, an IdP needs to redirect to a Google URL, passing the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRelayState\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e and \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSAMLResponse\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e. This is typically done by serving an HTML page that contains a hidden form which is submitted to the Google URL automatically upon page load. It is important to not actually submit the form until after the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e has been invoked. The recommended way to handle this is to call the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method upon page load, setting the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e to \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eform.submit.bind(form)\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, where \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eform\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is the DOM node representing the hidden form. This way, the form will be submitted automatically when Chrome has processed the credential and invokes the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf the credentials provided are incorrect, the IdP must not call the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecomplete\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method. When the SAML authentication flow completes with a \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSAMLResponse\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e indicating authentication failure, Chrome will inform the user of the authentication failure and will allow him/her to try again, starting a new authentication flow.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Limitations\" /\u003e\u003cspan\u003e\u003cfont size\u003d\"4\"\u003eLimitations\u003c/font\u003e\u003c/span\u003e\u003c/h4\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe API can be used to securely pass a key derived from the user’s password to Chrome. If the user authenticates using other means (e.g., smart card, biometrics, single-use codes) and does not have a password, the API cannot be used as no key can be derived. Support for other authentication types is a separate problem outside the scope of the API at this time.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe API is available in Chrome 36 and higher. Earlier Chrome versions behave like other user agents that do not support the API: It is safe to call the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e method. Since the API is not supported, the \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ecallback\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e passed to \u003c/span\u003e\u003cspan style\u003d\"font-family:Consolas;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003einitialize\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e will never be invoked.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7817060016656641064"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/administrators/advanced-integration-for-saml-sso-on-chrome-devices"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2260845138845475075"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2260845138845475075"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2260845138845475075"}],"author":[{"name":{"$t":"Saswat Panigrahi"},"email":{"$t":"saswat@chromium.org"}}],"sites$pageName":{"$t":"advanced-integration-for-saml-sso-on-chrome-devices"},"sites$revision":{"$t":"10"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/433193974057156045"},"published":{"$t":"2012-10-11T00:45:49.990Z"},"updated":{"$t":"2014-10-09T18:50:05.787Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-09T18:50:04.132Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Multithreaded Rasterization"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"font-weight:bold;font-size:medium;font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-nduca-enne-vangelis-and-many-others-\" /\u003e\u003cb style\u003d\"font-size:medium;font-weight:normal\"\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"display:inline!important\"\u003e\u003ca name\u003d\"TOC-nduca-enne-vangelis-and-many-others-1\" /\u003e\u003cb style\u003d\"font-size:medium;font-weight:normal\"\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"display:inline!important\"\u003e\u003ca name\u003d\"TOC-nduca-enne-vangelis-and-many-others-2\" /\u003e\u003cb style\u003d\"font-size:medium;font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e@nduca, @enne, @vangelis (and many others)\u003c/span\u003e\u003c/b\u003e\u003c/h2\u003e\u003c/b\u003e\u003c/h2\u003e\u003c/b\u003e\u003c/h2\u003e\u003cbr /\u003e\u003ch1 style\u003d\"font-weight:bold;font-size:medium;font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Implementation-status:\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImplementation status:\u003c/span\u003e\u003c/h1\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-crbug.com-169282-and-https:-code.google.com-p-chromium-issues-list-q-label:Cr-Internals-Compositing-Rasterization\" /\u003e\u003cfont size\u003d\"3\"\u003e\u003cspan style\u003d\"color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;font-weight:normal;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ecrbug.com/169282, and \u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont color\u003d\"#666666\" face\u003d\"arial, sans-serif\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/list?q\u003dlabel:Cr-Internals-Compositing-Rasterization\"\u003ehttps://code.google.com/p/chromium/issues/list?q\u003dlabel:Cr-Internals-Compositing-Rasterization\u003c/a\u003e\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/h1\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThis feature is referred to as \"multithreaded painting\" and \"impl-side painting\" in some forums.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Background-Problem-StatementOur-current-compositor-thread-architecture-is-built-around-the-idea-of-rasterizing-layers-on-the-main-webkit-thread-and-then-on-the-compositor-thread-drawing-the-bits-of-the-layers-that-we-have-based-on-their-various-animated-an\" /\u003e\u003cspan style\u003d\"background-color:transparent;color:rgb(102,102,102);font-family:Arial;font-size:16px;white-space:pre-wrap\"\u003eBackground \u0026amp; Problem Statement\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap;font-weight:normal\"\u003eOur current compositor thread architecture is built around the idea of rasterizing layers on the main webkit thread and then, on the compositor thread, drawing the bits of the layers that we have based on their various animated and scrolled positions. This allows us to move the page up and down, e.g. due to finger dragging, without having to block on the webkit thread. When a tile is exposed that does not have contents, we draw a checkerboard and wait for the main thread to rasterize that tile.\u003c/span\u003e\u003c/h2\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-We-want-to-be-able-to-fill-in-checkerboards-without-requiring-a-new-commit-since-that-requires-going-to-a-busy-webkit-thread-and-pulling-in-a-whole-new-tree-damage.-We-also-want-to-be-able-to-render-tiles-at-multiple-resolutions-and-quality-levels.-These-k\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt;display:inline!important\"\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;display:inline!important\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe want to be able to fill in checkerboards without requiring a new commit, since that requires going to a busy webkit thread and pulling in a whole new tree + damage. We also want to be able to render tiles at multiple resolutions, and quality levels. These kinds of tricks reduce memory pressure, avoid the jarring interruption of checkerboards.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h2\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-The-Excessive-Checkerboarding-ProblemA-lot-of-our-unwanted-checkerboarding-comes-from-invalidates-getting-intermixed-with-requests-from-the-impl-thread-to-fill-in-missing-tiles.-In-the-current-architecture-we-can-only-rasterize-tiles-on-the-main-thread-usi\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-size:medium;font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-The-Excessive-Checkerboarding-Problem\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe Excessive Checkerboarding Problem\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA lot of our unwanted checkerboarding comes from invalidates getting intermixed with \"requests\" from the impl thread to fill in missing tiles. In the current architecture, we can only rasterize tiles on the main thread, using webkit's rendering data structures. If webkit's rendering tree is completely unchanged, then the page scrolls, all the rasterization requests that go to the main thread are easily satisifed by webkit.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h2\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-However-any-time-javascript-changes-the-rendering-tree-we-have-the-following-problem:-we-have-some-newly-exposed-tiles-that-the-compositor-thread-needs-to-prevent-checkerboarding.-But-annoyingly-any-of-the-previously-painted-tiles-that-webkit-says-were-inv\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHowever, any time javascript changes the rendering tree, we have the following problem: we have some \"newly exposed tiles\" that the compositor thread needs to prevent checkerboarding. But, annoyingly, any of the previously-painted tiles that webkit says were invalidated. We can only paint the new rendering tree -- the old rendering tree is gone. So, we have two options at this point:\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1. Draw the new tiles with the new rendering tree, and redraw the old tiles with the new rendering tree\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2. Draw only the new tiles, and let the old tiles stick around.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e#2 doesn't work well at all, of course: if you have a page that toggles between green and blue constantly, what you'd see is a random mix of green and blue page at any given moment. We want to preserve the \"atomicity of rendering\" --- meaning that the complete state of a web page at rAF time is what gets put on the screen.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere is a variant on 2 where we draw the new tiles, as well as any old tiles that are *onscreen*. If a tile is offscreen, then we make a note that is is invalid, but dont repaint it. In the green-blue scenario, this causes the screen to be green or blue, but never both\u003cu\u003e, as long as you dont scroll\u003c/u\u003e. We ship this on Chrome Android m18. Even so, this is undesirable: if you scroll, you'll see a mix of content. This is expedient performance wise, but makes us all feel dirty.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Our-other-source-of-heavy-checkerboarding-is-latency-related.-The-work-we-do-on-the-main-thread-is-based-on-as-scroll-position-update-message-that-comes-from-the-impl-thread.-This-message-is-itself-not-very-latent-arriving-on-the-main-thread-milliseconds-a\" /\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:normal;white-space:pre-wrap\"\u003eOur other source of heavy checkerboarding is latency related. The work we do on the main thread is based on as scroll position update message that comes from the impl thread. This message is itself not very latent, arriving on the main thread milliseconds after it is sent. However, paints for a new set of tiles can take 300ms + to complete, even with the relaxed atomicity approach described above. By the time we have painted all 300ms worth of work, the page has scrolled way past the original scroll position, and half of the tiles we worked hard to prepare are irrelevant. We have discussed a variety of solutions here, but the real core problem is that the main thread cannot be updated fast enough with the new scroll positions to really ever keep up properly.\u003c/span\u003e\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:normal;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Planned-Solution\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:16px;font-weight:bold;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ePlanned Solution\u003c/span\u003e\u003c/h3\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Display-lists.-Namely-SkPictures-modified-a-bit-to-support-partial-updating.-We-call-this-a-Picture-pile-a-name-borrowed-from-the-awesome-folks-behind-Android-Browser.-The-idea-is-to-only-capture-a-display-list-of-the-webkit-rendering-tree-on-the-main-thre\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap;font-weight:normal\"\u003eDisplay lists. Namely, SkPictures, modified a bit to support partial updating. We call this a Picture pile, a name borrowed from the awesome folks behind Android Browser. \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-family:Arial;font-size:15px;font-weight:normal;white-space:pre-wrap\"\u003eThe idea is to only capture a display list of the webkit rendering tree on the main thread. Then, do rasterization on the impl thread, which is much more responsive.\u003c/span\u003e\u003c/h3\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-On-main-thread-web-content-is-turned-into-PictureLayers.-Picture-layers-make-a-recording-of-the-layer-into-a-PicturePile.-We-track-invalidations-in-SkRegions-and-during-the-display-list-capture-process-decide-between-re-capturing-the-entire-layer-or-just-g\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap;font-weight:normal\"\u003eOn main thread, web content is turned into PictureLayers. \u003c/span\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ePicture layers make a recording of the layer into a PicturePile. We track invalidations in SkRegions and during the display list capture process, decide between re-capturing the entire layer or just grabbing the invalidated area and drawing it on-top of the previously recorded base layer.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h3\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-During-commit-we-pass-these-PicturePiles-to-a-PictureLayerImpl.-Recall-layers-can-change-in-scale-over-time-under-animation-pinch-zoom-etc.-To-handle-this-a-PictureLayerImpl-manages-one-or-more-PictureLayerTiling-objects-via-a-PictureLayerTilingSet-which-i\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDuring commit, we pass these PicturePiles to a PictureLayerImpl. \u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRecall, layers can change in scale over time, under animation, pinch zoom, etc. To handle this, a PictureLayerImpl manages \u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eone or more PictureLayerTiling objects (via a PictureLayerTilingSet), which is a decomposition of the layer's entire contents into tiles at a picture screenspace resolution. So for example, a 512x512 layer might have a tiling into 4 256x256 tiles for a 1:1 ratio of screenspace pixels to content pixels, but also 1 256x256 tile for a 1:2 ratio of screenspace to conten space. We manage these tilings dyanmically.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h2\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-A-tiling-itself-takes-the-layers-entire-size-not-just-the-visible-part-and-breaks-it-up-into-Tiles.-Each-tile-represents-a-rectangle-of-the-PicturePile-painted-into-a-Resource-ID-think-GL-texture-at-a-given-resolution-and-quality-setting.\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA tiling itself takes the layers entire size, not just the visible part, and breaks it up into Tiles. Each tile represents a rectangle of the PicturePile painted into a Resource ID [think, GL texture], at a given resolution and quality setting.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eEvery tile is given a set of TilePriority values by the PictureLayerImpl based on its screen space position, animation and scroll velocity, and picture contents. These different priorities encode how soon, in time units, the tile could be visually useful onscreen. Key metrics are things like \"how soon will it be visible\" and \"how soon will it be crisp\" and \"is this a tile we'd use if a crisp one wasn't available?\"\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThese Tiles are registered to the \u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTileManager, which keeps these tiles sorted based on their priority and some global priority states. Tiles are binned in orders of urgency (needed now, needed in the next second, needed eventually, never going to be needed) and then sorted within their bin. The total GPU Memory budget is then assigned in decreasing priority order to these tiles. Tiles that are given permission to use memory are then added to a rasterization queue if needed.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe raster thread scheduler is a very simple solution: on the impl thread, we simply pop from the raster queue, dispatch the raster task. We keep a certain number of jobs enqueued per thread, opting to not enqueue them all so that if the prioritization changes much in the future, we wont do redundant work.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eJPEG/PNG/etc bitmaps are stored in the display lists in still-encoded form to keep display list recording cost low and memory footprint small. Thus, the first time we draw a bitmap, a costly decode and downsample operation may be needed. \u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThus, before dispatch, tiles are \"cracked open\" to determine whether any bitmaps need to be decompressed, using the SkLazyPixelRef interface to WebCore's ImageDecodingStore. If decoding is needed, the tile is held in a side queue while a decoding task is dispatched to the raster threads. When the decodes are done, raster tasks are enqueued.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-This-approach-fixes-the-atomicity-of-commits-problem-by-allowing-us-to-servie-checkerboard-misses-without-havin-to-go-to-the-laggy-potentially-changed-main-thread.-In-the-previous-example-when-the-compositor-sees-a-checkerboarded-tile-we-can-rasterize-it-w\" /\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-This-approach-fixes-the-atomicity-of-commits-problem-by-allowing-us-to-servie-checkerboard-misses-without-havin-to-go-to-the-laggy-potentially-changed-main-thread.-In-the-previous-example-when-the-compositor-sees-a-checkerboarded-tile-we-can-rasterize-it-w1\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis approach fixes the “atomicity of commits” problem by allowing us to servie checkerboard misses without havin to go to the laggy, potentially changed main thread. In the previous example, when the compositor sees a checkerboarded tile, we can rasterize it without having to start a commit flow, allowing us to disallow commits entirely during flings and other heavy animation use cases.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h3\u003e\u003c/b\u003e\u003c/h2\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Hitch-free-commitsA-key-challenge-with-this-approach-is-switching-from-the-old-tree-to-the-new-tree.-In-the-existing-architecture-when-we-go-to-switch-to-the-new-tree-we-have-painted-and-uploaded-all-the-tiles-so-the-tree-can-be-immediately-switched.In-the\" /\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Hitch-free-commitsA-key-challenge-with-this-approach-is-switching-from-the-old-tree-to-the-new-tree.-In-the-existing-architecture-when-we-go-to-switch-to-the-new-tree-we-have-painted-and-uploaded-all-the-tiles-so-the-tree-can-be-immediately-switched.In-the1\" /\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline\"\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Hitch-free-commitsA-key-challenge-with-this-approach-is-switching-from-the-old-tree-to-the-new-tree.-In-the-existing-architecture-when-we-go-to-switch-to-the-new-tree-we-have-painted-and-uploaded-all-the-tiles-so-the-tree-can-be-immediately-switched.In-the2\" /\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"color:rgb(0,0,0);font-family:Times New Roman;font-size:medium;white-space:normal\"\u003e\u003ca name\u003d\"TOC-Hitch-free-commits\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHitch-free commits\u003c/span\u003e\u003c/h3\u003e\u003c/b\u003e\u003cb style\u003d\"font-size:20px;font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-A-key-challenge-with-this-approach-is-switching-from-the-old-tree-to-the-new-tree.-In-the-existing-architecture-when-we-go-to-switch-to-the-new-tree-we-have-painted-and-uploaded-all-the-tiles-so-the-tree-can-be-immediately-switched.\" /\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA key challenge with this approach is switching from the old tree to the new tree. In the existing architecture, when we go to switch to the new tree, we have painted and uploaded all the tiles, so the tree can be immediately switched.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn the impl-side painting architecture, we need to create PictureLayerImpl's in order to begin rasterizing them. Moreover, those impls need to be attached together to the LayerTreeHostImpl in order to get their screenspace positions, which are essential in computing their priorities.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe obvious way to do this is to simply commit the main tree to the impl tree like we usually do. However, if we do that, then the impl tree now has holes in it where there were invalidations. At this point, the impl-side has two options when vsync comes around: checkerboard, or drop the frame. Neither is very cool.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman;font-size:medium;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOur solution is the LayerTreeImpl. Whereas the previous architecture's LayerTreeHostImpl had a root layer and all its associated state, we instead introduce LayerTreeImpl, which has all the state associated with a layer tree: scrolling info, viewport, background color, etc. The LTHI then stores not one, but two LayerTreeImpl's: the active tree is the one we are drawing, while the pending tree is the one we are rasterizing. Priority is given to the active tree, but once the pending tree is fully painted, we activate it and throw away the old one. This allows us to switch between old and new trees without janking.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003c/b\u003e\u003c/h2\u003e\u003c/span\u003e\u003c/h3\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Handling-Giant-SkPictures\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHandling Giant SkPictures\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOne potential challenge to impl-side painting compared to our existing painting model is that the SkPicture for a given layer are potentially unbounded. We plan to mitigate this by limiting the PicturePile's size to a 10,000px (emperically determined) \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eportion of the total layer size cenetered around the viewport at the time of the picture pile's first creation. When the impl thread starts needing tiles outside the pile's area, we will asynchronously trigger the main thread to go update the pile around the new viewport center.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cb style\u003d\"font-size:10pt;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"display:inline!important\"\u003e\u003ca name\u003d\"TOC-Choosing-the-scale-at-which-to-raster\" /\u003e\u003cfont color\u003d\"#666666\" face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eChoosing the scale at which to raster\u003c/span\u003e\u003c/font\u003e\u003c/h3\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;white-space:pre-wrap\"\u003eWhenever we compute the draw properties for a PictureLayerImpl, we also decide what tilings it should have, or in other words, at what scales it should have sets of tiles. To do this we track two scale values: The ideal scale, and the raster scale. The ideal scale is the scale at which we should create tiles to give the texels in the tile a 1:1 correspondence with pixels on the screen. The raster scale is the high-resolution scale at which we are currently creating tiles. When we set the raster scale to be equal to the ideal scale, we get crisp tiles. This is what we'd like to have at all times, but we limit this for performance reasons. During a pinch gesture, or an accelerated animation, the raster scale lags behind the ideal scale. CSS can change the scale of a layer through the DOM, and we limit how often it is allowed to change the raster scale. This decision to reset the raster scale to the ideal or leave it alone is made in PictureLayerImpl::ManageTilings. Whenever the raster scale changes, we add a tiling both at the raster scale, and at a low resolution related to the raster scale. These tilings are marked as HIGH_RESOLUTION and LOW_RESOLUTION and are given priority as we raster tiles for the layer.\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-size:10pt;font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"display:inline!important\"\u003e\u003ca name\u003d\"TOC-Texture-Upload\" /\u003e\u003cfont color\u003d\"#666666\" face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eTexture Upload\u003c/span\u003e\u003c/font\u003e\u003c/h3\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOne key challenge on lowend devcies is that uploading a single 256x256 texture can take many milliseconds, sometimes as crazy as 3-5ms. Because of this, we have to carefully throttle our texture uploads so that we dont drop a frame. To do this, we are adopting a new approach of async texture uploads. Instad of issuing standard glTexImage calls, we instead place textures into shared memory and then instruct the GPU process to do the upload when-convenient. This enables the GPU process to do the upload during idle times, or even on another thread. The compositor then polls the GPU process via the query infrastructure to determine if the upload is complete. Only when the upload is complete will we draw with it.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Handling-setPictureListener\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHandling setPictureListener\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf the embedder has a picture listener, we need to send a serialized SkPicture to the embedding process. We would need to, at every impl-side swapbuffers, serialize our SkPictures for all the active layers (plus the bitmaps) and send them to the main thread.\u003c/span\u003e\u003c/b\u003e\u003c/b\u003e\u003cdiv\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:16px;color:rgb(102,102,102);background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eFollowup Work\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe initial impl-side painting implementation is expected to enable the following followup use cases:\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium;margin-left:36pt;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eLow-res tiles: \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor tiles that take a long time to rasterize, we may want to rasterize them at half or third resolution. This often dramatically reduces (5-6x anecdotally) raster cost and allows us to avoid checkerboarding during fling. However, it is worth noting that some Android users criticized this behavior on ICS devices as making fonts look too ugly. High-dpi devices may change the UX impact of this behavior on users.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium;margin-left:36pt;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eJust-in-time scaling: \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe currently do resizing of content at many layers in the pipeline. For example, we rasterize layers at their content resolution without consideration to their screenspace transform. Thus, a layer that is -webkit-transform: scale(0.5)’d will actually paint at its full size. Similarly, we resize images inside webkit at their content resolution. We could reduce rasterization/decode costs and memory footprint if we could do all of this scaling using the draw-time transforms on the impl thread.\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium;margin-left:36pt;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cbr /\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-size:medium;margin-left:36pt;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eAccelerated painting: \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAn interesting property of impl-side painting is that it cleans up our accelerated painting story. We would store the SkPicture for a layer, and then can decide to rasterize a layer with the GPU without having to involve the main thread at all in the process.\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"font-family:Times New Roman;font-size:medium\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/b\u003e\u003c/b\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/impl-side-painting"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/433193974057156045"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/433193974057156045"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/433193974057156045"}],"author":[{}],"sites$pageName":{"$t":"impl-side-painting"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"Xyl7JmA4\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6898459593441562844"},"published":{"$t":"2010-12-08T21:46:07.630Z"},"updated":{"$t":"2014-10-06T23:19:17.111Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-10-06T23:19:15.770Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Cr-48 Chrome Notebook Developer Information"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eEntering Developer Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Getting-the-recovery-kernel\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eGetting the recovery kernel\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving-Developer-Mode\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eLeaving Developer Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-use-the-Recovery-Mode-button\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eHow to use the Recovery Mode button\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-boot-your-own-non-Chromium-OS-image-from-USB\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eHow to boot your own (non-Chromium OS) image from USB\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Getting-the-recovery-kernel-for-your-Chrome-OS-Notebook\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003eGetting the recovery kernel for your Chrome OS Notebook\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Creating-a-USB-disk-that-will-boot-a-simple-script\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003eCreating a USB disk that will boot a simple script\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Create-the-script\"\u003e\u003cstrong\u003e6.2.1 \u003c/strong\u003eCreate the script\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Build-a-disk-image\"\u003e\u003cstrong\u003e6.2.2 \u003c/strong\u003eBuild a disk image\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Find-your-USB-disk\"\u003e\u003cstrong\u003e6.2.3 \u003c/strong\u003eFind your USB disk\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Format-your-USB-disk-with-the-disk-image\"\u003e\u003cstrong\u003e6.2.4 \u003c/strong\u003eFormat your USB disk with the disk image\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Boot-your-Chrome-OS-Notebook-with-your-USB-image\"\u003e\u003cstrong\u003e6.2.5 \u003c/strong\u003eBoot your Chrome OS Notebook with your USB image\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Create-a-USB-disk-that-will-boot-another-operating-system\"\u003e\u003cstrong\u003e6.3 \u003c/strong\u003eCreate a USB disk that will boot another operating system\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Install-your-own-build-of-Chromium-OS\"\u003e\u003cstrong\u003e6.4 \u003c/strong\u003eInstall your own build of Chromium OS\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Install-your-image-to-the-Cr-48-s-SSD\"\u003e\u003cstrong\u003e6.4.1 \u003c/strong\u003eInstall your image to the Cr-48's SSD\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-install-a-different-OS-on-your-SSD\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eHow to install a different OS on your SSD\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Troubleshooting\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eTroubleshooting\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Battery-Doesn-t-Charge\"\u003e\u003cstrong\u003e8.1 \u003c/strong\u003eBattery Doesn't Charge\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e9 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e10 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Components\"\u003e\u003cstrong\u003e10.1 \u003c/strong\u003eComponents\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e10.2 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cdiv\u003eThis page contains information about the \u003ca href\u003d\"http://www.google.com/chromeos/pilot-program-cr48.html\"\u003eCr-48 Chrome Notebook\u003c/a\u003e that is interesting and/or useful to software developers.  For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Entering-Developer-Mode\" /\u003eEntering Developer Mode\u003c/h2\u003e\r\n\u003cdiv\u003eYou might want to enter developer mode if you're following the instructions in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e, or if you just want to get access to a shell on your device to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device\"\u003epoke around\u003c/a\u003e.  To get your device into Developer Mode, you'll need to flip the developer switch to the \"Developer Mode\" position.  \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware issues and may void warranty.\u003c/span\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe first time a Chrome Notebook boots in Developer Mode after leaving Normal Mode it will:\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eShow\r\n a scary warning that its software cannot be trusted, since verified \r\nboot is disabled (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003eErase all personal data on the \"stateful partition\" (i.e., user accounts and settings - no worries, though, since all data is in the cloud!).\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eMake you wait between 5 and 10 minutes to while it erases the data.\u003cbr /\u003e\r\n\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eBoot from any self-signed image on its SSD, negating the security of verified boot.\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\nThe erase and wait steps only happen when you first switch to Developer Mode, to help prevent someone from quickly reimaging your device while you're away from the keyboard. Successive boots in Developer Mode will only:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eShow a scary warning that its software cannot be trusted, since verified boot is disabled (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eBoot from any self-signed image on its SSD, negating the security of verified boot.\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\nEntering Developer mode is easy:\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003eRemove the battery.\u003c/li\u003e\r\n\u003cli\u003ePeel off the sticker that hides the developer switch (see image 1).\u003c/li\u003e\r\n\u003cli\u003eFlip the developer switch towards the battery connector (see image 2).\u003c/li\u003e\r\n\u003cli\u003ePut the battery back in.\u003c/li\u003e\r\n\u003cli\u003eTurn the device back on.\u003c/li\u003e\r\n\u003cli\u003ePress Ctrl-D at the scary warning screen.\u003c/li\u003e\r\n\u003cli\u003eWait 5-10 minutes and any saved information on your device will be erased.\u003c/li\u003e\r\n\u003cli\u003eCongratulations, enjoy hacking in Developer Mode!\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eHere are some pictures that might help:\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/Mario_DevSwitchTape.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"225\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1291846639209/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/Mario_DevSwitchTape.png\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cb\u003eImage 1: Location of Developer Switch\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/Mario_DevSwitchOn.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"225\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1291846931759/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/Mario_DevSwitchOn.png\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eImage 2: Developer Switch in \"Developer Mode\" position.\u003c/b\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003chr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Getting-the-recovery-kernel\" /\u003eGetting the recovery kernel\u003c/h2\u003e\r\n\u003cdiv\u003eIf you are trying to install your own disk image onto your Cr-48 Chrome Notebook (maybe you're following the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Instructions\u003c/a\u003e), you need the recovery kernel.  You can find it at: \u003ca href\u003d\"https://dl.google.com/dl/edgedl/chromeos/recovery/mario_recovery_kernel.zip\"\u003ehttps://dl.google.com/dl/edgedl/chromeos/recovery/mario_recovery_kernel.zip\u003c/a\u003e (this did not work for me, and I had to follow \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/extracting-a-recovery-kernel-from-a-recovery-image\" target\u003d\"_blank\"\u003ethese instructions\u003c/a\u003e instead).\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003chr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Leaving-Developer-Mode\" /\u003eLeaving Developer Mode\u003c/h2\u003e\r\nReturning to normal mode is as simple as entering developer mode: shut down, remove the battery, flip the switch, reboot. There are a couple of things to note, however.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nFirst, assuming you haven't modified anything, the first time you boot \r\nin normal mode after leaving developer mode, the stateful partition will\r\n be erased. This is a much faster erase process than when entering \r\ndeveloper mode, usually only 30 or 40 seconds, and only happens with the\r\n first boot.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nSecond, verified boot will be enabled, meaning that only Google-signed images will be bootable. If you haven't modified the original kernel or rootfs partitions in any way, you should have no problems. If you've made changes to the kernel partitions, the Cr-48 will refuse to boot that kernel and will display a recovery screen. You'll have to \u003ca href\u003d\"http://www.google.com/chromeos/recovery\"\u003ecreate a recovery USB drive\u003c/a\u003e to restore your Cr-48 to the factory condition. If you've made changes to the rootfs partition but not the kernel, the Cr-48 \u003cb\u003emay\u003c/b\u003e appear to boot normally, but may later suddenly reboot and/or display the recovery screen. This happens because the kernel verifies the rootfs as each block is read from the SSD, so it may not encounter a modified block until sometime later. When it does, it will reboot immediately.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-use-the-Recovery-Mode-button\" /\u003eHow to use the Recovery Mode button\u003c/h2\u003e\r\nRecovery mode is a special boot operation in which the BIOS will:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003eRefuse to boot from the SSD\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003ePrompt you to insert a recovery USB drive\u003c/li\u003e\r\n\u003cli\u003eOnly boot a Google-signed image from the USB drive\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\nYou will encounter recovery mode when the BIOS is unable to find a valid kernel to boot, either because the SSD has become corrupted or (more likely) because you modified all the kernel partitions while in developer mode and have switched back to normal mode. While in developer mode, you will be presented with the scary boot screen at every boot. Pressing SPACE or RETURN will take you to recovery mode.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nYou can also force your Cr-48 into recovery mode (even in normal mode) by using the recovery mode button.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nOn the bottom of the Cr-48, directly below the ESC key, there is a tiny pinhole:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/cr48_recovery_button.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1293483840456/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/cr48_recovery_button.jpg\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nIf you stick a paperclip into this hole, you'll feel it press a button. To force recovery mode, turn the Cr-48 off, press this button, and while keeping it pressed, turn the Cr-48 on again. This sometimes requires three hands or a bit of contortion, but you'll know it worked when you see the recovery screen instead of booting normally.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThere is little use for this button other than booting a \u003ca href\u003d\"http://www.google.com/chromeos/recovery\"\u003erecovery USB drive\u003c/a\u003e. In developer mode you can run your own scripts from the recovery USB drive, but in developer mode you can trigger recovery mode by just pressing SPACE at boot. Still, there it is.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-boot-your-own-non-Chromium-OS-image-from-USB\" /\u003eHow to boot your own (non-Chromium OS) image from USB\u003cbr /\u003e\r\n\u003c/h2\u003e\u003cdiv\u003e(Note: This part is outdated: \u003cspan style\u003d\"color:rgb(153,0,255);font-family:monospace;line-height:13px;font-size:10pt;background-color:rgb(239,239,239)\"\u003emake_developer_script_runner.sh\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e does not exist anymore)\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003eSometimes,\r\n you just want to have a shell or maybe you want to install another \r\noperating system.  If you're in Developer Mode, then you can totally do \r\nthat.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThis tip could actually be useful \r\nto someone who wasn't a Chromium OS developer.  However, at the moment \r\nthe only easy way to get the tools is to follow many of the steps in \r\nthe \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\" style\u003d\"color:rgb(0,102,204);outline-style:none\"\u003eChromium OS Developer Guide\u003c/a\u003e.\r\n  If you don't care about developing for Chromium OS and just want to \r\nget to booting your own stuff, you should read the developer guide with \r\nthese thoughts in mind:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003eThe instructions in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\" style\u003d\"color:rgb(0,102,204);outline-style:none\"\u003eChromium OS Developer Guide\u003c/a\u003e assume that you're running the \u003ca href\u003d\"http://www.ubuntu.com/\" style\u003d\"color:rgb(0,102,204);outline-style:none\" rel\u003d\"nofollow\"\u003eUbuntu Lucid\u003c/a\u003e distribution of Linux.  If you're not, you may not be able to follow them.\u003c/li\u003e\r\n\u003cli\u003eYou\r\n should only need to follow the instructions up to the point of \"Enter \r\nthe chroot\".  You don't actually need to build a Chromium OS image.  You\r\n probably also want to choose the \"minilayout\" when downloading the \r\nsource code, since that will be faster.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cdiv\u003eThe rest of the \r\ninstructions will assume that you've followed the instructions enough to\r\n make a chroot and that you're currently in the chroot.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Getting-the-recovery-kernel-for-your-Chrome-OS-Notebook\" /\u003eGetting the recovery kernel for your Chrome OS Notebook\u003c/h3\u003e\r\n\u003cdiv\u003eYou'll\r\n need to get a \"recovery kernel\" for your Chrome OS Notebook in order to\r\n follow these instructions. You can download the an\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e officially-signed Recovery Kernel for the \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information\" style\u003d\"background-color:transparent;font-size:10pt;color:rgb(0,102,204)\"\u003eCr-48 Chromebook\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e (AKA Mario) by running the steps below from inside the chroot:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003ecurl https://dl.google.com/dl/edgedl/chromeos/recovery/mario_recovery_kernel.zip \u0026gt; ~/trunk/mario_recovery_kernel.zip\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003eunzip -d ~/trunk ~/trunk/mario_recovery_kernel.zip\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont color\u003d\"#9900ff\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003eRECOVERY_KERNEL\u003d~/trunk/mario_recovery_kernel.bin\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eThe instructions below assume that you've set the \u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003eRECOVERY_KERNEL\u003c/font\u003e\u003c/code\u003e variable as above.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIf you have trouble downloading the recovery kernel, you might be able to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/extracting-a-recovery-kernel-from-a-recovery-image\" style\u003d\"background-color:transparent;font-size:10pt;color:rgb(0,102,204)\"\u003eextract an officially-signed Recovery Kernel from an officially-signed Recovery Image\u003c/a\u003e instead.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Creating-a-USB-disk-that-will-boot-a-simple-script\" /\u003eCreating a USB disk that will boot a simple script\u003c/h3\u003e\r\n\u003cdiv\u003eUsing the \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003emake_developer_script_runner.sh\u003c/font\u003e\u003c/code\u003e tool,\r\n you can create a USB disk that will run shell script.  In this example,\r\n we'll show how to create a USB disk with a script that will leave you \r\nrunning the shell.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Create-the-script\" /\u003eCreate the script\u003c/h4\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"background-color:rgb(239,239,239);border:1px solid rgb(211,211,211);display:block;padding:0.5em 0px 0.5em 1em;line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003eecho -e  '#!/bin/sh\\nexec /bin/sh\\n' \u0026gt; run_a_shell.sh\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Build-a-disk-image\" /\u003eBuild a disk image\u003c/h4\u003e\r\n\u003cdiv\u003eNow, use \u003cspan style\u003d\"font-family:monospace;color:rgb(153,0,255)\"\u003emake_developer_script_runner.sh\u003c/span\u003e.  The script will create a file called \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003edev_runner_image.bin\u003c/font\u003e\u003c/code\u003e that can be placed on a USB disk.  Note that these instructions assume that you've set the \u003cspan style\u003d\"font-family:monospace;color:rgb(153,0,255);line-height:13px\"\u003eRECOVERY_KERNEL\u003c/span\u003e variable properly, as explained above.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"background-color:rgb(239,239,239);border:1px solid rgb(211,211,211);display:block;padding:0.5em 0px 0.5em 1em;line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e./make_developer_script_runner.sh --kernel_image\u003d${RECOVERY_KERNEL} --developer_script\u003drun_a_shell.sh\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Find-your-USB-disk\" /\u003eFind your USB disk\u003c/h4\u003e\r\nYou\r\n should plug a USB disk in to your computer now and wait a few seconds \r\nfor it to be detected.  You can then run this quick command to use some \r\nChromium OS tools to detect the disk and find out where it is:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"background-color:rgb(239,239,239);border:1px solid rgb(211,211,211);display:block;padding:0.5em 0px 0.5em 1em;line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003ebash -c 'source chromeos-common.sh; \u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e  echo\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e  for disk in $(list_usb_disks); \u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e    do echo /dev/$disk - $(get_disk_info $disk manufacturer) - $(get_disk_info $disk product); \u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e  done'\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n...assuming\r\n your disk was detected, it should print out as a result of that \r\ncommand.  For instance, on my computer, I see this, which tells me that \r\nmy USB disk is in \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e/dev/sdc\u003c/font\u003e\u003c/code\u003e:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"background-color:rgb(239,239,239);border:1px solid rgb(211,211,211);display:block;padding:0.5em 0px 0.5em 1em;line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e/dev/sdc - Kingston - DataTraveler G3\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Format-your-USB-disk-with-the-disk-image\" /\u003eFormat your USB disk with the disk image\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cb\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cu\u003eWARNING\u003c/u\u003e: This step will erase all data on your USB disk.  Make sure there's nothing important on it.  \u003c/font\u003e\u003c/b\u003e\u003cbr /\u003e\r\n\u003cfont color\u003d\"#ff0000\"\u003e\u003cb\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/font\u003e\u003cb\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cu\u003eALSO\u003c/u\u003e: If you mistype this step (don't put the right /dev/sdX in the command), it can blow away some other disk on your computer.  \u003c/font\u003e\u003c/b\u003e\u003cbr /\u003e\r\n\u003cfont color\u003d\"#ff0000\"\u003e\u003cb\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/font\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cfont color\u003d\"#ff0000\"\u003eBE CAREFUL!  \u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont color\u003d\"#ff0000\"\u003eReally, I'm serious\u003c/font\u003e.  \u003ci\u003e\u003cfont color\u003d\"#ff0000\"\u003eBe very careful\u003c/font\u003e\u003c/i\u003e.  If you shoot yourself in the foot with these instructions, you only get to blame yourself.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eOK, now that you've read all of the disclaimers, the command you'll need to enter is this, replacing \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e${MY_USB_KEY_LOCATION}\u003c/font\u003e\u003c/code\u003e with the \u003cspan style\u003d\"font-family:monospace;color:rgb(153,0,255)\"\u003e/dev/sdX\u003c/span\u003e value that is for your USB disk (see the \"Find your USB disk\" instruction above).\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont color\u003d\"#ff0000\"\u003eTODO:\r\n You may need to unmount your USB disk before running this instruction \r\nif Ubuntu mounted it for you.  Put a set of instructions that tell how \r\nto do that\u003c/font\u003e.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"background-color:rgb(239,239,239);border:1px solid rgb(211,211,211);display:block;padding:0.5em 0px 0.5em 1em;line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e\u003cfont color\u003d\"#9900ff\"\u003esudo dd if\u003ddev_runner_image.bin of\u003d${MY_USB_KEY_LOCATION} bs\u003d16M conv\u003dfsync\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Boot-your-Chrome-OS-Notebook-with-your-USB-image\" /\u003eBoot your Chrome OS Notebook with your USB image\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNow,\r\n shut off your Chrome OS Notebook and turn it back on.  Since you're in \r\nDeveloper Mode (right?), you should see the warning.  Hit the space bar \r\nto enter recovery mode.  Once prompted, insert your USB disk.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eAssuming\r\n that you haven't reimaged the built-in SSD with a developer-signed \r\nimage, you'll need to wait 5 minutes each time you boot up with this \r\ndisk image.  This is a security precaution, to prevent someone from quickly rebooting your device from their USB key while you're getting more coffee (see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/developer-mode\"\u003eDeveloper Mode\u003c/a\u003e design document).\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003chr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Create-a-USB-disk-that-will-boot-another-operating-system\" /\u003eCreate a USB disk that will boot another operating system\u003c/h3\u003e\r\n\u003cdiv\u003eTODO:\r\n This should be possible for someone skilled in the art of Linux.  The \r\nabove instructions tell you how to run any arbitrary Linux program, and \r\n(with root access) you should be able to do pretty much anything you \r\nwant.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIt would be nice to get some good instructions here, though.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003chr size\u003d\"2\" width\u003d\"100%\" /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Install-your-own-build-of-Chromium-OS\" /\u003e\u003cfont size\u003d\"4\"\u003eInstall your own build of Chromium OS\u003c/font\u003e\u003c/h3\u003e\r\n\u003cdiv\u003eFirst, download the recovery kernel, as explained above. Then build a Chromium OS image, as mentioned in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\" style\u003d\"background-color:transparent;font-size:10pt\"\u003eChromium OS Developer Guide\u003c/a\u003e. Once you have the recovery kernel and the OS image, you'll stitch them together, copy them to a USB drive, and then boot your system from the USB drive.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-weight:bold\"\u003eCombine the recovery kernel and your OS image, to create a recovery image\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eYou can build your own recovery image using \u003c/span\u003e\u003ccode style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cfont color\u003d\"#9900ff\"\u003emod_image_for_recovery.sh\u003c/font\u003e\u003c/code\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e.  This image will have the officially-signed Recovery Kernel (so you can boot from USB) and will install a self-signed SSD image (so you can boot only with developer mode).  Here's the magic set of steps (assuming that you've got a path to the recovery kernel in\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003ccode style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e${RECOVERY_KERNEL}\u003c/font\u003e\u003c/code\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eand that the recovery kernel is a match for the\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003ccode style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cfont color\u003d\"#9900ff\"\u003e${BOARD}\u003c/font\u003e\u003c/code\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eyou built):\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e./mod_image_for_recovery.sh \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --board\u003d${BOARD} \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --nominimize_image \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --kernel_image ${RECOVERY_KERNEL} \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --image ~/trunk/src/build/images/${BOARD}/latest/chromiumos_image.bin\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cb\u003eSIDE NOTE\u003c/b\u003e: If you're interested in creating a test image (used for allowing Chromium OS to talk to autotest), you can run\u003cfont color\u003d\"#9900ff\"\u003e build_image test\u003c/font\u003e to create a test image that can be combined with the recovery image:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,255);font-family:monospace\"\u003e./build_image --board\u003d${BOARD} test\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,255);font-family:monospace\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,255);font-family:monospace\"\u003e./mod_image_for_recovery.sh \\\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"line-height:13px\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --board\u003d${BOARD} \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"line-height:13px\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --nominimize_image \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"line-height:13px\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --kernel_image ${RECOVERY_KERNEL} \\\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"line-height:13px\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003e    --image ~/trunk/src/build/images/${BOARD}/latest/chromiumos_test_image.bin\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-weight:bold\"\u003eCopy the recovery image to a USB key\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003eThe first step is to insert a USB flash disk (4 GB or bigger) into your build computer. \u003cb\u003e\u003cfont color\u003d\"#e69138\"\u003eThis disk will be completely erased, so make sure it doesn't have anything important on it\u003c/font\u003e\u003c/b\u003e.  Wait ~10 seconds for the USB disk to register, then type the following command:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\u003ccode\u003e\u003cfont color\u003d\"#9900ff\"\u003ecros flash --board\u003d${BOARD} usb://\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cp\u003eFor more details on using this tool, see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/build/cros-flash\"\u003eCros Flash page\u003c/a\u003e.\u003c/p\u003e\u003c/div\u003e\r\n\u003cdiv\u003eWhen the \u003cspan style\u003d\"font-family:monospace;color:rgb(153,0,255);line-height:13px\"\u003ecros flash\u003c/span\u003e command finishes, you can simply unplug your USB key and it's ready to boot from.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cfont color\u003d\"#e69138\"\u003eIMPORTANT NOTE\u003c/font\u003e\u003c/b\u003e: To emphasize again, \u003cspan style\u003d\"font-family:monospace;color:rgb(153,0,255);line-height:13px\"\u003ecros flash\u003c/span\u003e completely replaces the contents of your USB disk. Make sure there is nothing important on your USB disk before you run this command.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch4 style\u003d\"margin-top:2em\"\u003e\u003ca name\u003d\"TOC-Install-your-image-to-the-Cr-48-s-SSD\" /\u003eInstall your image to the Cr-48's SSD\u003c/h4\u003e\r\n\u003cdiv\u003eIn developer mode, your Chrome OS Notebook gives you an option to use a recovery image every time the machine boots. To install your recovery image, do the following:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli style\u003d\"margin-top:0.2em\"\u003eTurn your Chrome OS Notebook off.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0.2em\"\u003eTurn it back on.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0.2em\"\u003eDuring the boot warning, press space to enter recovery mode.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0.2em\"\u003eWait until prompted to put your USB disk in.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0.2em\"\u003ePut the USB disk in.\u003c/li\u003e\r\n\u003cli style\u003d\"margin-top:0.2em\"\u003eWait while the image is copied to the SSD.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cdiv\u003eIf you reboot now, you'll be booting from your image (you may need to wait past the recovery screen).  Congratulations!\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cfont color\u003d\"#e69138\"\u003eIMPORTANT NOTE\u003c/font\u003e\u003c/b\u003e: You \u003cb\u003emust\u003c/b\u003e stay in Developer Mode to continue booting your image. Since your image was not signed by the release keys (it's self-signed image), it will only boot in Developer Mode. If you want to go back to Release Mode, just copy (/bin/dd) \u003ca href\u003d\"http://support.google.com/chromeos/bin/answer.py?hl\u003den\u0026amp;answer\u003d1080595\"\u003ea recovery image\u003c/a\u003e directly to a USB drive, without making any modifications to it.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\r\n\u003cdiv\u003e\r\n\u003chr /\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-install-a-different-OS-on-your-SSD\" /\u003eHow to install a different OS on your SSD\u003c/h2\u003e\r\n\u003cp\u003eThere's an example of configuring a Cr-48 to dual-boot Chrome OS and Ubuntu \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/how-to-boot-ubuntu-on-a-cr-48\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Troubleshooting\" /\u003eTroubleshooting\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Battery-Doesn-t-Charge\" /\u003eBattery Doesn't Charge\u003c/h3\u003e\r\n\u003cp\u003eIf your battery is completely drained, sometimes the CR-48 has trouble charging it again. You might be able to workaround it by doing:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003ePlug the AC adapter in\u003c/li\u003e\r\n\u003cli\u003eWait 20 seconds\u003c/li\u003e\r\n\u003cli\u003eUnplug the AC adapter\u003c/li\u003e\r\n\u003cli\u003eWait 20 seconds\u003c/li\u003e\r\n\u003cli\u003ePlug the AC adapter in\u003c/li\u003e\r\n\u003cli\u003eWait 20 seconds\u003c/li\u003e\r\n\u003cli\u003e... repeat this cycle 10 times or so ...\u003c/li\u003e\r\n\u003cli\u003eThe battery should hopefully start charging again\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eSee the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/h2c-firmware\"\u003eH2C firmware page\u003c/a\u003e for more details.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Components\" /\u003eComponents\u003c/h3\u003e\r\n\u003cp\u003eHere is a rundown of the parts that are not soldered down:\u003c/p\u003e\r\n\r\n\u003cul\u003e\u003cli\u003ePower supply: 19.5V \u003cimg border\u003d\"0\" height\u003d\"5\" src\u003d\"http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices/direct-current.svg?attredirects\u003d0\u0026amp;d\u003d1\" /\u003e (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Direct_current\" rel\u003d\"nofollow\"\u003eDC\u003c/a\u003e) 2.05A \u003cimg height\u003d\"12\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1364850218094/chromium-os/developer-information-for-chrome-os-devices/center-positive-polarity.svg\" /\u003e (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Polarity_symbols\" rel\u003d\"nofollow\"\u003epositive polarity tip\u003c/a\u003e)\u003c/li\u003e\r\n\u003cli\u003eSSD: 16GiB mSATA\u003c/li\u003e\r\n\u003cli\u003eRAM: one slot for 204-Pin DDR3 SO-DIMM laptop memory\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance from a friend knowledgeable in the area.  \u003cspan style\u003d\"font-size:10pt\"\u003eIf you just want to see what the inside looks like, gaze upon this (click for a high res version):\u003c/span\u003e\u003c/p\u003e\r\n\u003cp style\u003d\"text-align:center\"\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/mario-bottom-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"231\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362459992190/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/mario-bottom-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/mario-top-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"102\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1360699328215/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information/mario-top-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\u003cp\u003eHowever, we acknowledge that some people like to tinker.  So here's a quick guide to taking it apart:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eShut the system down and close the lid\u003c/li\u003e\r\n\u003cli\u003eFlip the laptop over so the bottom is facing up\u003c/li\u003e\r\n\u003cli\u003ePop out the battery using the release switch in the middle of the case\u003c/li\u003e\r\n\u003cli\u003eRemove the visible screws\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThere should be 10 in total (a line of 3 black, a line of 3 silver, and a line of 4 silver)\u003c/li\u003e\r\n\u003cli\u003eThe black screws are \u003cspan style\u003d\"font-family:arial,sans,sans-serif;white-space:pre-wrap\"\u003eM2x2x0.4 while the silver screws are \u003c/span\u003e\u003cspan style\u003d\"margin:0px;padding:0px;border:0px;vertical-align:baseline;font-size:12.800000190734863px;font-family:arial,sans,sans-serif;white-space:pre-wrap\"\u003eM2x3x0.4\u003c/span\u003e\u003cbr style\u003d\"font-size:12.800000190734863px;font-family:arial,sans,sans-serif;white-space:pre-wrap\" /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove the two screws under the rubber feet (\u003cspan style\u003d\"font-family:arial,sans,sans-serif;white-space:pre-wrap\"\u003eM2.5x6x0.45)\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIf you pry them up starting at the edge closest to the hinge, you're less likely to strip the glue\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eUsing a flat instrument (your nails, a wide screw driver, etc...), pry the case apart starting at the side w/the VGA port\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWork your way around the front and to the other side\u003c/li\u003e\r\n\u003cli\u003eBy now, it should be pretty easy to wiggle the whole thing apart\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cp\u003eYou now have access to the upgradable components.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/cr-48-chrome-notebook-developer-information"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6898459593441562844"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6898459593441562844"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6898459593441562844"}],"author":[{"name":{"$t":"Douglas Anderson"},"email":{"$t":"dianders@chromium.org"}}],"sites$pageName":{"$t":"cr-48-chrome-notebook-developer-information"},"sites$revision":{"$t":"46"}},{"gd$etag":"\"Wil7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3701056214207182036"},"published":{"$t":"2010-09-02T16:02:56.715Z"},"updated":{"$t":"2014-10-01T23:26:51.032Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-30T19:21:37.918Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Vulnerability Rewards Program"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\r\n\u003cdiv style\u003d\"text-align:left\"\u003e\u003cdiv style\u003d\"text-align:left\"\u003e\u003cfont size\u003d\"3\"\u003eThe Chrome Reward Program is hosted at \u003ca href\u003d\"https://www.google.com/about/appsecurity/chrome-rewards/index.html\"\u003ehttps://www.google.com/about/appsecurity/chrome-rewards/index.html\u003c/a\u003e. \u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"text-align:left\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"text-align:left\"\u003e\u003cfont size\u003d\"3\"\u003eGo forth and report bugs!\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6743906577140407009"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/vulnerability-rewards-program"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3701056214207182036"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3701056214207182036"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3701056214207182036"}],"author":[{"name":{"$t":"Justin Schuh"},"email":{"$t":"jschuh@chromium.org"}}],"sites$pageName":{"$t":"vulnerability-rewards-program"},"sites$revision":{"$t":"23"}},{"gd$etag":"\"YDUpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5679784314495825094"},"published":{"$t":"2014-02-12T15:23:05.629Z"},"updated":{"$t":"2014-09-29T18:12:06.492Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-29T18:12:04.592Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Blink GC Plugin Errors"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\u003cdiv\u003eWith the addition of the new Blink garbage collection infrastructure we have created a clang compiler plugin to statically check various conditions are met. This page documents what conditions are checked, which error a failed condition will raise and how the error might be fixed.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAll diagnostics produced by the checker are prefixed with \u003cfont face\u003d\"courier new, monospace\"\u003e[blink-gc]\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e.\u003c/font\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Tracing-Errors\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eTracing Errors\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eAll members of a class must be traced in order to ensure that the GC system does not reclaim their storage space. Thus, if a class contains any fields that need to be traced (ie, the field is either a GC managed object or it also contains fields that need to be traced), then the class must implement a trace method to do so.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you get the error:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eClass 'Foo' requires a trace method\u003cspan style\u003d\"font-size:10pt\"\u003e because it contains fields that require tracing.\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ethen your class/struct contains fields that need to be traced and you must define a trace method doing so. The plugin will provide a note describing which fields that need to be traced. A problematic class might look like:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_baz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThis is fixed by defining a trace method and tracing the field \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003em_baz\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_baz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  virtual void trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you get the error:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eClass 'Foo' overrides non-virtual trace of base class 'Bar'.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ethen your class/struct has overridden a non-virtual trace method of a base class and the base class should either be virtual or the hierarchy needs to implement manual trace dispatching (see the section on Dispatch Errors below).\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you get the errors:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eBase class 'Foo' of derived class 'Bar' requires tracing.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eClass 'Bar' has untraced fields that require tracing.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ethen your class/struct has a trace method, but it does not trace all of the required parts. The base class tracing ensures that fields declared in base classes are traced. The plugin will provide a note describing which fields that need to be traced. A problematic class might look like:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Bar : public Foo {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheOtherBaz() { return m_otherBaz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  void trace(Visitor* visitor) { }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_otherBaz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThis is fixed by tracing \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eFoo\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e and \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003em_otherBaz\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Bar : public Foo {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e  Baz* getTheOtherBaz() { return m_otherBaz; }\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e  void trace(Visitor* visitor)\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e  {\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e    visitor-\u0026gt;trace(m_otherBaz);\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e    Foo::trace(visitor);\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt\"\u003e\u003cfont color\u003d\"#38761d\"\u003e  }\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_otherBaz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Field-Errors\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eField Errors\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIn order to ensure proper tracing, each field of a class is checked against some correctness requirements described below.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you get the errors:\u003c/font\u003e\u003c/div\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eClass 'Foo' contains invalid fields.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eClass 'Foo' contains GC root in field 'm_bar'.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ethen your class/struct contains problematic fields. If a field points to a GC allocated object then it should be in a Member, so if the field is currently a raw pointer, RefPtr or OwnPtr, it should be changed to a Member or WeakMember and properly traced. A problematic class might look like:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_baz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  OwnPtr\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003eHere Baz is a GC allocated type and the issue is fixed by replacing the OwnPtr by Member and tracing the field:\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_baz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  virtual void trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003eAnother type of invalid field is the embedding of or a pointer to a stack-allocated object from within A GC allocated object. This is simply not permitted and the containing class must also be stack allocated or the stack-allocated object must become GC allocated.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf a field inside a GC allocated object either defines a GC root (ie, Persistent or PersistentHeapXXX collection) or embeds a GC root via a part object, then we likely have a memory leak. In this case the Persistent should be replaced by a properly traced Member. A problematic case might look like:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Part {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace\"\u003e  DISALLOW_ALLOCATION();\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003eBaz* getTheBaz() { return m_baz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Persistent\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_part.getTheBaz(); }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Part m_part;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003eHere Part is used as a part object of Foo and it contains a Persistent pointer to Baz. To fix the issue the Persistent should be replaced by Member and Part should be traced:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Part {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  DISALLOW_ALLOCATION();\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_baz; }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  void trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:courier new,monospace;font-size:10pt\"\u003e};\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:courier new,monospace;font-size:10pt\"\u003e  Baz* getTheBaz() { return m_part.getTheBaz(); }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  virtual void trace(Visitor* visitor) { visitor-\u0026gt;trace(m_part); }\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  Part m_part;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Finalization-Errors\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eFinalization Errors\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eWhen an object is allocated on the GC managed heap it might need finalization support. Objects that derive a GC base with finalization support will be finalized on the first GC where they have become unreachable. Thus the\u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e finalization time (ie, time of destruction) is not known in advance. By default finalization of an object will call the objects destructor. If a class does not have finalization support its destructor will never be called. The existence of destructors that are never called can hide subtle bugs and so we check agains this with the GC plugin. The basic rule is that a class with a \"non-trivial destructor\" must have finalization support. A class has a trivial destructor if and only if the destructor is the default generated destructor and all of the class bases and members have trivial destructors.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you get the error:\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e Class 'Foo' requires finalization.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ethen your class/struct has a \"non-trivial finalizer\" and therefore needs to inherit from a finalized GC base class, such as, GarbageCollectedFinalized. The plugin will try to emit notes about which bases, members and destructors are causing the class to have a non-trivial finalizer. \u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003eFor example:\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  ~Foo();\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e};\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ewill issue a note about a \"user-declared destructor\". The destructor can then either be removed or finalization support can be added to the class:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollectedFinalized\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(56,118,29);font-family:courier new,monospace;font-size:10pt\"\u003e  ~Foo();\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you get the error:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e Finalizer '~Foo' accesses potentially finalized field 'm_baz'.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ethen your finalizer is accessing a field of Foo that might be finalized in the same GC round. In other words, the object pointed to by m_baz might already be reclaimed by the GC. For example:\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e  ~Foo { m_baz-\u0026gt;doSomeCleanup(); }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt\"\u003e   void trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eneeds to be changed to perform the cleanup of baz in some other way dependent on the concrete situation. Maybe the cleanup code can be moved into the finalization of Baz.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Dispatch-Errors\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eDispatch Errors\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eSome places in the Blink code base avoid introducing a vtable for a class hierarchy, such as the CSSValue class hierarchy. In such cases the programmer needs to define the dispatch methods manually.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you get the errors:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eClass 'Foo' is missing manual trace dispatch.\u003c/li\u003e\u003cli\u003eClass 'Foo' is missing manual finalization dispatch.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eyour class needs to define a trace method and/or a finalizeGarbageCollectedObject method to perform the manual dispatch.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you get the errors:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eClass 'Foo' contains or inherits virtual methods but implements manual dispatching.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eyour class has implemented manual dispatch but might be able to simply have a virtual trace and destructor.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you get the errors:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eMissing dispatch to class 'Bar' in manual trace dispatch.\u003c/li\u003e\u003cli\u003eMissing dispatch to class 'Bar' in manual finalize dispatch.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ethen the derived class 'Bar' is not dispatched to from the manually implemented dispatch.\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Derived-Class-Errors\" /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eDerived Class Errors\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eIf you get the error:\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eClass 'Foo' must derive its GC base in the left-most position.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ethen the class Foo inherits from a GC base, but does so incorrectly. To ensure\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e that the vtable entry and GC meta data of a class is mapped to a reliable location in memory, w\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ee require that the GC base is always inherited in the left-most position in the super-class declarations. For example:\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public Bar, public GarbageCollected\u0026lt;Foo\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003evoid trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eneeds to swap the position of Bar and the GC base:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt;, \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003epublic Bar\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003e {\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/font\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003evoid trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe same is true if the GC base is inherited from some other derived class, say Baz, then the super-class declaration of Baz must be in the left-most position.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you get the error:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eLeft-most base class 'Bar' of derived class 'Foo' must be polymorphic.\u003c/li\u003e\u003cli\u003eLeft-most base class 'Bar' of derived class 'Foo' must define a virtual trace method.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ethen the base class 'Bar' needs to be polymorphic and if 'Foo' has a virtual trace method then it must be declared virtual in 'Bar'. The requirement is to ensure that the GC have a consistent view of a vtable/virtual-trace even if a GC happens while an object is only partially constructed. In both cases, the typical fix will simply be to define a virtual trace in 'Bar', override it in 'Foo' and trace the super class there. For example:\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Bar : public GarbageCollected\u0026lt;Bar\u0026gt; {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Bar(); // could potentially trigger a GC.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public Bar {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  virtual \u003c/font\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003evoid trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eneeds to define trace in 'Bar' and trace it in 'Foo':\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eclass Bar : public GarbageCollected\u0026lt;Bar\u0026gt; {\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Bar();\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  virtual void trace(Visitor*) { }\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eclass Foo : \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003epublic Bar\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003e {\u003c/span\u003e\u003c/span\u003e\u003c/font\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003evoid trace(Visitor* visitor)\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003e  {\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003e    visitor-\u0026gt;trace(m_baz);\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003e    Bar::trace(visitor);\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;font-size:10pt;background-color:transparent\"\u003e  }\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eprivate:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you get the error:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eStack-allocated class 'Foo' derives class 'Bar' which is not stack allocated\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ethen either class Foo can not be annotated as \"stack allocated\", or class Bar must be annotated \"stack allocated\" and used as such. A stack allocated class cannot be new'ed, ie, allocated on the managed heap or using any other kind of allocator. For example:\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Bar {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003evoid someMethod();\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003e};\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003eclass Foo : public Bar {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  STACK_ALLOCATED();\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(153,0,0);font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003eprivate:\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#990000\" face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003eneeds to either make Bar stack allocated:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Bar {\u003c/font\u003e\u003c/div\u003e\u003c/span\u003e\u003cdiv\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e  STACK_ALLOCATED();\u003c/font\u003e\u003c/div\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003evoid someMethod();\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003e};\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eclass Foo : public Bar {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-family:courier new,monospace;font-size:10pt\"\u003eprivate:\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003eNotice that the stack allocated annotation is inherited and that a stack allocated object does not need to define a trace method: its pointers are found conservatively on the stack.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAlternatively, Foo can be made GC allocated:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003eclass Bar {\u003c/font\u003e\u003c/span\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;color:rgb(56,118,29);font-size:10pt\"\u003epublic:\u003c/span\u003e\u003c/div\u003e\u003cfont color\u003d\"#38761d\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003evoid someMethod();\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003e};\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eclass Foo : public GarbageCollected\u0026lt;Foo\u0026gt;, public Bar {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003epublic:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace;background-color:transparent;font-size:10pt\"\u003evoid trace(Visitor* visitor) { visitor-\u0026gt;trace(m_baz); }\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-family:courier new,monospace;font-size:10pt\"\u003eprivate:\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Member\u0026lt;Baz\u0026gt; m_baz;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e};\u003c/font\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/blink-gc-plugin-errors"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5679784314495825094"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5679784314495825094"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5679784314495825094"}],"author":[{"name":{"$t":"Ian Zerny"},"email":{"$t":"zerny@chromium.org"}}],"sites$pageName":{"$t":"blink-gc-plugin-errors"},"sites$revision":{"$t":"9"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1785392819850875949"},"published":{"$t":"2014-09-27T01:38:59.489Z"},"updated":{"$t":"2014-09-27T01:39:15.520Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-27T01:39:15.520Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1785392819850875949"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1785392819850875949"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1785392819850875949"}],"author":[{"name":{"$t":"Nodir Turakulov"},"email":{"$t":"nodir@chromium.org"}}],"sites$revision":{"$t":"2"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/a/google.com/document/d/1qQS8dZ5_wt3iOZ44vYmfrAn3EsAIkwFh9sAMdDPraQE/edit\"\u003e.dbconfig files loss on master3\u003c/a\u003e"},{"index":"B","name":"Date","$t":"2014-09-19"}]},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5997370119992053850"},"published":{"$t":"2011-01-04T08:47:37.688Z"},"updated":{"$t":"2014-09-26T01:21:06.519Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-26T01:21:05.369Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Fixing Google Chrome compatibility bugs in websites - FAQ"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2 style\u003d\"margin-top:0px\"\u003e\u003ca name\u003d\"TOC-NOTE:-The-information-on-this-page-is-out-of-date.\" /\u003e\u003cfont color\u003d\"#ff0000\" face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003eNOTE: The information on this page is out of date.\u003c/font\u003e\u003c/h2\u003e\u003ch2 style\u003d\"font-family:arial,sans-serif\"\u003e\u003ca name\u003d\"TOC-This-page-mostly-contains-information-from-2011.-Since-then-Chrome-has-switched-its-rendering-engine-to-Blink-a-fork-of-WebKit-.\" /\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal;background-color:transparent\"\u003e\u003cfont color\u003d\"#cc0000\"\u003eThis page mostly contains information from 2011. Since then, Chrome has switched its rendering engine to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/blink\"\u003eBlink\u003c/a\u003e (a fork of WebKit).\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003ch2 style\u003d\"font-family:arial,sans-serif;font-size:large\"\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2 style\u003d\"font-family:arial,sans-serif;font-size:large\"\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"TOC-This-document-provides-a-concise-list-of-common-compatibility-issues-with-Google-Chrome-along-with-their-solutions.-It-s-aimed-at-Web-developers-trying-to-fix-compatibility-issues-with-Google-Chrome-or-interested-in-a-list-of-things-to-avoid-when-authoring\" /\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal\"\u003eThis document provides a concise list of common compatibility issues with Google Chrome along with their solutions. It's aimed at Web developers trying to fix compatibility issues with Google Chrome or interested in a list of things to avoid when authoring Websites to use in Google Chrome.\u003c/span\u003e\u003c/h1\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eThe list is based on analysis of a large number of real-world sites with compatibility issues. It's important to note that in nearly all cases we've seen, the fixes required to get a Website working well in Google Chrome have been minimal. Developers are often surprised that problems that looked like they could take weeks of developer time were often solved in under an hour and matched closely with the list below.\u003c/p\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eEach item is described along with its solution, at the end we have a section that lists useful tools and points of reference that you may find useful in diagnosing problems.\u003c/p\u003e\u003ch2 style\u003d\"font-family:arial,sans-serif;font-size:large\"\u003e\u003ca name\u003d\"TOC-Preamble---Google-Chrome-s-rendering-Engine:\" /\u003ePreamble - Google Chrome's rendering Engine:\u003c/h2\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eGoogle Chrome uses WebKit (\u003ca href\u003d\"http://webkit.org/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ehttp://webkit.org/\u003c/a\u003e) to draw Web pages. WebKit is a mature (~9 years) open source layout engine used by Apple (Safari, iPhone), Google (Android, Google Chrome), Nokia and many other companies. Google Chrome aims to render sites exactly like Safari. This means that if your site works in Safari there is a large chance it will work in Google Chrome and vice versa.\u003c/p\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"TOC-Common-Issues:\" /\u003eCommon Issues:\u003c/h1\u003e\u003cul style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#UserAgent_Detection\" style\u003d\"color:rgb(0,0,204)\"\u003eUserAgent Detection\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#Paragraphs_Overflowing/Text_Cutoff\" style\u003d\"color:rgb(0,0,204)\"\u003eParagraphs Overflowing/Text Cutoff\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#Correct_page_encoding\" style\u003d\"color:rgb(0,0,204)\"\u003eCorrect page encoding\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#Correct_Plugin_Tags\" style\u003d\"color:rgb(0,0,204)\"\u003eCorrect Plugin Tags\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#Use_of_Browser-Specific_CSS_or_JavaScript_objects\" style\u003d\"color:rgb(0,0,204)\"\u003eUse of Browser-Specific CSS or JavaScript objects\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#Useful_Tools\" style\u003d\"color:rgb(0,0,204)\"\u003eUseful Tools\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/doctype/wiki/ArticleGoogleChromeCompatFAQ#Additional_Resources\" style\u003d\"color:rgb(0,0,204)\"\u003eAdditional Resources\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"UserAgent_Detection\" /\u003eUserAgent Detection\u003c/h1\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-Symptom\" /\u003eThe Symptom\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003ePage not displayed correctly in Google Chrome, or you get a message noting that Google Chrome is not a \"supported browser\".\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-problem\" /\u003eThe problem\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eBy far the most common problem we see is JavaScript (or server-side) code that tries to detect the browser by looking at the \u003ctt style\u003d\"font-size:13px\"\u003enavigator.userAgent\u003c/tt\u003e string. Often the checks used are buggy and do not identify Google Chrome correctly.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-Recommendations:\" /\u003eRecommendations:\u003c/h3\u003e\u003cul style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eDo everything you can to avoid this, parsing \u003ctt style\u003d\"font-size:13px\"\u003enavigator.userAgent\u003c/tt\u003e and \u003ctt style\u003d\"font-size:13px\"\u003enavigator.vendor\u003c/tt\u003e is \u003ca href\u003d\"http://my.opera.com/hallvors/blog/2008/12/19/10-is-the-one\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003enotoriously bug-prone\u003c/a\u003e and usually the wrong thing to do! \u003ca href\u003d\"http://www.quirksmode.org/js/support.html\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eObject detection\u003c/a\u003e is a much safer method to achieve per-browser behavior...\u003c/li\u003e\u003c/ul\u003e\u003cul style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eOn Windows, Google Chrome's useragent string looks something like the following:\u003c/li\u003e\u003cpre style\u003d\"font-size:12px;margin-left:2em;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:0.5em;border-left-width:3px;border-left-style:solid;border-left-color:rgb(204,204,204)\"\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e     \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eMozilla\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e/\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e5.0\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eWindows\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e U\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eWindows\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e NT \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e5.1\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e en\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e-\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003eUS\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e)\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eAppleWebKit\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e/\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e525.13\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003eKHTML\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e,\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e like \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eGecko\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e)\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eChrome\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e/\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e2.0\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e167.0\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eSafari\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e/\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e525.13\u003c/span\u003e\u003c/pre\u003e\u003c/ul\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eIn nearly all cases you don't want to check if you're running under Google Chrome, but if the browser is using the WebKit rendering engine (see above). If you must look at the \u003ctt style\u003d\"font-size:13px\"\u003enavigator.userAgent\u003c/tt\u003e string look for the substring \u003ctt style\u003d\"font-size:13px\"\u003e'AppleWebKit'\u003c/tt\u003e, nothing else is guaranteed to continue working in the future!!\u003c/p\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;font-size:12px;margin-left:2em;padding:0.5em;border-left-width:3px;border-left-style:solid;border-left-color:rgb(204,204,204)\"\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003evar\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e isWebKit \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u003d\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e  navigator\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003euserAgent\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003eindexOf\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"AppleWebKit\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e)\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e-\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e1\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e;\u003c/span\u003e\u003c/pre\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003e\u003ctt style\u003d\"font-size:13px\"\u003eisWebKit\u003c/tt\u003e will be \u003ctt style\u003d\"font-size:13px\"\u003etrue\u003c/tt\u003e if you're running in Google Chrome, Safari or any other browser using WebKit.\u003c/p\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eTo check the version of WebKit, use:\u003c/p\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;font-size:12px;margin-left:2em;padding:0.5em;border-left-width:3px;border-left-style:solid;border-left-color:rgb(204,204,204)\"\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003evar\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eWebKitVersion\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u003d\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e  parseFloat\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003enavigator\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003euserAgent\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003esplit\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"AppleWebKit/\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e)[\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e1\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e])\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e||\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e  \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eundefined\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eif\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eWebKitVersion\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003eWebKitVersion\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,102,102)\"\u003e500\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e)\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e{\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e  \u003c/span\u003e\u003cspan style\u003d\"color:rgb(136,0,0)\"\u003e// use spiffy WebKit feature here\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eYou can find a list of Google Chrome Releases and their corresponding WebKit revisions \u003ca href\u003d\"http://dev.chromium.org/developers/webkit-version-table\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ehere\u003c/a\u003e.\u003c/p\u003e\u003cul style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eAvoid code like the following:\u003c/li\u003e\u003c/ul\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;font-size:12px;margin-left:2em;padding:0.5em;border-left-width:3px;border-left-style:solid;border-left-color:rgb(204,204,204)\"\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eif\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e(\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003eisChrome\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e)\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e{\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e    doSomethingChromeSpecific\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e();\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e}\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003eelse\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e{\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e  \u003c/span\u003e\u003cspan style\u003d\"color:rgb(136,0,0)\"\u003e// Didn't detect browser type, so assume IE.\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e  doSomethingIESpecific\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e();\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e}\u003c/span\u003e\u003c/pre\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eThe problem is that the above snippet assumes that any browser not explicitly identified is IE. The problem is that it's far more likely for other browsers to act alike than it is for them to act like IE. And IE9 is very similar to all other browsers, so the code fork is bound to fail. Stick to feature detection instead.\u003c/p\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"Paragraphs_Overflowing/Text_Cutoff\" /\u003eParagraphs Overflowing/Text Cutoff\u003c/h1\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-Symptom:\" /\u003eThe Symptom:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eA single line header wraps over multiple lines, messing up a site's layout. Text gets cut off or overlaps other elements.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-problem:\" /\u003eThe problem:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eHTML \u0026amp; CSS can't do pixel perfect layout. So font and element sizes can change slightly between browser versions and OSs. If a site depends on a font being an exact size then text can get cut off or wrap on other browsers or OSs.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-Recommendations:1\" /\u003eRecommendations:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eWhenever possible, make use of dynamically sized elements rather than specifying fixed pixel widths. This is often easier said than done, but it ensures that content will adapt well to all browsers. Test your site in multiple browsers and OSs, enlarge fixed pixel width elements to accommodate the maximum size you see. Use the white-space:nowrap css attribute to ensure that single line headings don't wrap over multiple lines.\u003c/p\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"Correct_page_encoding\" /\u003eCorrect page encoding\u003c/h1\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-Symptom:1\" /\u003eThe Symptom:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eYour page looks garbled in Google Chrome. Garbage characters may be displayed, and RTL language pages (e.g. Hebrew or Arabic) may appear with their letters reversed.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-problem:1\" /\u003eThe problem:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eIf character encoding is not specified precisely, different browsers can interpret the encoding in different ways or not at all. The impact on users is dire since it prevents them from viewing the site.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-Recommendations:2\" /\u003eRecommendations:\u003c/h3\u003e\u003cul style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eDeclare your page's content-type correctly, this can either be in an \u003ca href\u003d\"http://www.w3.org/International/tutorials/tutorial-char-enc/#Slide0270\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eHTTP header\u003c/a\u003e or a \u003ca href\u003d\"http://code.google.com/p/doctype/wiki/MetaCharsetAttribute\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eMeta tag specified in your HTML\u003c/a\u003e.\u003c/li\u003e\u003cli\u003eThe character set your page uses must be a legal value from the \u003ca href\u003d\"http://www.iana.org/assignments/character-sets\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eOfficial IANA List\u003c/a\u003e, please only use the encodings that have the text (preferred MIME name) listed next to them e.g. ISO-8859-1, Shift_JIS.\u003c/li\u003e\u003cli\u003eIf you specify two different values for the character encoding in the HTTP Header and the Meta tag, Google Chrome will use the value in the HTTP Header. Conflicting declarations of character encoding in the HTTP Header and Meta tag is asking for trouble. More information on this subject can be \u003ca href\u003d\"http://blog.whatwg.org/the-road-to-html-5-character-encoding\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003efound here\u003c/a\u003e.\u003c/li\u003e\u003cli\u003eWe recommend using UTF-8 for all Web content. If you have to use legacy encoding for some reason, make sure to identify the encoding correctly as outlined above. For legacy situations involving Hebrew sites use \u003ca href\u003d\"http://www.w3.org/International/geo/html-tech/tech-bidi.html#ri20030112.21380914\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eLogical Hebrew encoding (ISO-8859-8-I)\u003c/a\u003e. We strongly \u003cstrong\u003ediscourage\u003c/strong\u003e the use of Visual Hebrew encoding (ISO-8859-8). It has no place on the Web anymore and is a remnant of old systems lacking logic for rendering RTL text. It causes many bugs and lots of confusion.\u003c/li\u003e\u003c/ul\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"Correct_Plugin_Tags\" /\u003eCorrect Plugin Tags\u003c/h1\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-Symptom:2\" /\u003eThe Symptom:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003ePlug-ins, such as Flash videos, Windows Media Player movies, or Java applets, do not appear in Google Chrome, but do appear in Internet Explorer.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-problem:2\" /\u003eThe problem:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eThere are 2 types of plugins on Windows: ActiveX \u0026amp; NPAPI. IE uses ActiveX plugins, all other browsers (including Google Chrome) use NPAPI plugins. ActiveX is Windows-only, plugins on other platforms usually use NPAPI.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-Recommendations:3\" /\u003eRecommendations:\u003c/h3\u003e\u003col style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eDo not use plug-ins for which only an Active-X version exists, they won't work in Google Chrome, Firefox, Safari, Opera or any browser not using the IE rendering engine.\u003c/li\u003e\u003cli\u003eBe sure that parameters in your \u003ctt style\u003d\"font-size:13px\"\u003e\u0026lt;object\u0026gt;\u003c/tt\u003e and \u003ctt style\u003d\"font-size:13px\"\u003e\u0026lt;embed\u0026gt;\u003c/tt\u003e tags are the same. A common problem is changing the parameter in only one of the tags, for example:\u003c/li\u003e\u003c/ol\u003e\u003cpre style\u003d\"font-family:arial,sans-serif;font-size:12px;margin-left:2em;padding:0.5em;border-left-width:3px;border-left-style:solid;border-left-color:rgb(204,204,204)\"\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026lt;object\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e ...\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e    \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026lt;param\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003ename\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u003d\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"src\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003evalue\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u003d\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"flash_ad.swf\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e\u003cbr /\u003e    \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026lt;embed\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,0,102)\"\u003esrc\u003c/span\u003e\u003cspan style\u003d\"color:rgb(102,102,0)\"\u003e\u003d\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,136,0)\"\u003e\"different_file.swf\"\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e ...\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,0)\"\u003e \u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,0,136)\"\u003e\u0026lt;/object\u0026gt;\u003c/span\u003e\u003c/pre\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eThis embeds a flash video. IE will use the parameters in the object tag and thus will load the file \u003cstrong\u003eflash_ad.swf\u003c/strong\u003e. All other browsers will use the embed tag and play \u003cstrong\u003edifferent_file.swf\u003c/strong\u003e. Another common error is to specify different values for the transparency attribute when embedding flash.\u003c/p\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"Use_of_Browser-Specific_CSS_or_JavaScript_objects\" /\u003eUse of Browser-Specific CSS or JavaScript objects\u003c/h1\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif\"\u003e\u003ca name\u003d\"TOC-The-Symptom:3\" /\u003eThe Symptom:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eSome CSS styling does not work in Google Chrome, even though they seem fine in IE or Firefox.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-The-problem:3\" /\u003eThe problem:\u003c/h3\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eEach browser has its own private CSS selectors and JavaScript objects. Use of these types of markup is, by definition, not compatible with other browsers. These should only be used for non-critical tasks (e.g. adding text shadows). It is safest not to use them at all.\u003c/p\u003e\u003ch3 style\u003d\"font-family:arial,sans-serif;font-size:medium;border:0px;padding:0.5ex 0.5em 0.5ex 0px;margin:0px;background-color:initial\"\u003e\u003ca name\u003d\"TOC-Recommendations:4\" /\u003eRecommendations:\u003c/h3\u003e\u003cul style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eDo not use \u003ca href\u003d\"http://simonwillison.net/2003/Aug/11/documentAll/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003edocument.all\u003c/a\u003e in JavaScript. This is an outdated IE feature, all modern browsers support \u003ca href\u003d\"https://developer.mozilla.org/En/Document.getElementById\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003edocument.getElementById()\u003c/a\u003e and you should \u003ca href\u003d\"http://www.w3schools.com/HTMLDOM/dom_nodes_access.asp\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003euse that instead\u003c/a\u003e.\u003c/li\u003e\u003cli\u003eWhen diagnosing JavaScript issues, use Google Chrome's \u003ca href\u003d\"http://www.google.com/chrome/intl/en/webmasters-faq.html#jsexec\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ebuilt-in JavaScript debugger\u003c/a\u003e.\u003c/li\u003e\u003cli\u003eDo not use browser-specific (e.g. \u003ctt style\u003d\"font-size:13px\"\u003e-moz-*\u003c/tt\u003e, \u003ctt style\u003d\"font-size:13px\"\u003e-webkit-*\u003c/tt\u003e, \u003ctt style\u003d\"font-size:13px\"\u003e-ie-*\u003c/tt\u003e) css selectors such as \u003ctt style\u003d\"font-size:13px\"\u003e-moz-center\u003c/tt\u003e or \u003ctt style\u003d\"font-size:13px\"\u003e-webkit-highlight\u003c/tt\u003e for critical visual features of your site, instead use standard CSS.\u003c/li\u003e\u003cli\u003eDo not use \u003ca href\u003d\"http://msdn.microsoft.com/en-us/library/ms537634%28VS.85%29.aspx\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eCSS expressions\u003c/a\u003e (e.g. \u003ctt style\u003d\"font-size:13px\"\u003ewidth:expression()\u003c/tt\u003e). These only work in IE, \u003ca href\u003d\"http://blogs.msdn.com/ie/archive/2008/10/16/ending-expressions.aspx\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003ehave serious performance issues and have been deprecated\u003c/a\u003e.\u003c/li\u003e\u003c/ul\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"Useful_Tools\" /\u003eUseful Tools\u003c/h1\u003e\u003cp style\u003d\"font-family:arial,sans-serif;max-width:65em\"\u003eWe've found the following tools extremely useful when diagnosing compatibility problems with Websites. Using them can greatly decrease the amount of effort and guesswork that goes into fixing compatibility issues:\u003c/p\u003e\u003col style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003eGoogle Chrome has a \u003ca href\u003d\"http://www.google.com/support/chrome/bin/answer.py?hl\u003den\u0026amp;answer\u003d95691\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003evariety of built-in tools\u003c/a\u003e to help developers track down compatibility and performance issues.\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://getfirebug.com/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eFirebug\u003c/a\u003e - An excellent Firefox extension that can help examining markup, JavaScript and performance issues.\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://www.fiddler2.com/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eFiddler\u003c/a\u003e - A free Windows-only tool that allows you to examine and replay HTTP requests and responses.\u003c/li\u003e\u003c/ol\u003e\u003ch1 style\u003d\"font-family:arial,sans-serif;font-size:x-large;margin-top:0px\"\u003e\u003ca name\u003d\"Additional_Resources\" /\u003eAdditional Resources\u003c/h1\u003e\u003col style\u003d\"font-family:arial,sans-serif;max-width:65em;padding-left:40px\"\u003e\u003cli\u003e\u003ca href\u003d\"http://www.google.com/chrome/intl/en/webmasters-faq.html\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eGoogle Chrome Webmaster FAQ\u003c/a\u003e - Contains all the information in this document and loads more.\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://www.quirksmode.org/\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003equirksmode\u003c/a\u003e - Useful Information about which features are implemented in which browser.\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://dev.chromium.org/for-testers/bug-reporting-guidelines\" rel\u003d\"nofollow\" style\u003d\"color:rgb(0,0,204)\"\u003eReporting a bug in Google Chrome\u003c/a\u003e - guidelines and pointers on how to write an effective clear bug report.\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4852676552341181359"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromecompatfaq"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5997370119992053850"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5997370119992053850"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5997370119992053850"}],"author":[{"name":{"$t":"Jeremy Moskovich"},"email":{"$t":"jeremy@chromium.org"}}],"sites$pageName":{"$t":"chromecompatfaq"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3043262643730806746"},"published":{"$t":"2014-09-19T16:30:03.827Z"},"updated":{"$t":"2014-09-22T23:11:03.278Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-22T23:11:01.518Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"check_gpu_bots script"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eThis is a script I hacked up during my wrangling shift. Hopefully this is only a temporary measure, and will be deprecated by the awesome work being done on the hackability CY and the sheriff-o-matic.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Purpose\" /\u003ePurpose\u003c/h4\u003e\u003cdiv\u003eWhile wrangling, I found it cumbersome and time consuming to keep track of various waterfalls in a browser window with 10+ tabs. This script is meant to be a quick-and-dirty way to avoid having to stare at the waterfalls quite so much during a shift.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-How-to-get-it\" /\u003eHow to get it\u003c/h4\u003e\u003cdiv\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/how-tos/gpu-wrangling/check_gpu_bots-script/check_gpu_bots.py?attredirects\u003d0\"\u003eHere\u003c/a\u003e is an older version of the script available for direct download for convenience, but there will be little continued support for it. The canonical version is now checked into the Chromium repository at src/gpu/tools/check_gpu_bots.py.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Features\" /\u003eFeatures\u003c/h4\u003e\u003cdiv\u003eThe script, when run directly with no args, simply polls the waterfall's \u003ca href\u003d\"http://build.chromium.org/p/chromium/json/help\"\u003eJSON API\u003c/a\u003e, gathers some information about (hopefully all of) the relevant GPU bots. It then prints out a summary of the offline or failing bots, and exits.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIt can also be set up to repeat itself periodically, sort of like an auto-refresh.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe feature that made it most useful to me is that it can also optionally email you when there's something that needs to be looked into. By default, \"needs to be looked into\" is roughly defined as\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003ethere is at least one bot whose most recent build failed, and whose most recent build had passed on the previous execution of the script, OR\u003c/li\u003e\u003cli\u003ethere is at least one bot which has been in the \"offline\" state for over an hour, and hadn't been the last time the script executed\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eAs described above, it only sends an email \u003ci\u003eonce\u003c/i\u003e per bot, the first time something goes wrong. I did that to prevent getting spammed. Currently this can't be overridden with command-line arguments, but I intend to add the ability to override this.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eNOTE\u003c/b\u003e that currently only gmail addresses are supported as the source email address, since the script hard-codes gmail's smtp server address. In addition, if you use a weak password, gmail may require you to explicitly allow \"\u003ca href\u003d\"https://support.google.com/accounts/answer/6010255\"\u003eless secure apps\u003c/a\u003e\".\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRunning the script on repeat, and having it set up to email you in case of a problem, takes away a good deal of staring at waterfalls. I recommend that you take a look at the waterfall from time to time, just because this script is not time-tested, and bugs aren't outside the realm of possibility.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Examples\" /\u003eExamples\u003c/h3\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e./check_gpu_bots.py\u003c/li\u003e\u003cul\u003e\u003cli\u003eThis runs once, and prints the results to stdout.\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e./check_gpu_bots.py --help\u003c/li\u003e\u003cul\u003e\u003cli\u003eThis prints basic usage information, including the list of possible command-line arguments.\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e./check_gpu_bots.py --email-from \u0026lt;source email\u0026gt; --email-to \u0026lt;dest email\u0026gt; --send-email-on-error --repeat-delay 10\u003c/li\u003e\u003cul\u003e\u003cli\u003e'--repeat-delay 10' sets the script to poll the waterfall every 10 minutes. '--send-email-on-error' tells the script to email you in case of error/exception (for example, an unreachable server), as well as the normal cases. The rest tells the script to send an email from \u0026lt;source email\u0026gt; to \u0026lt;dest email\u0026gt;. You do have to be in control of \u0026lt;source email\u0026gt; and will need to supply the password, either by saving it in a file on disk, or supplying it to the script's prompt. If you opt to save the password on disk, it is very strongly recommended that you use a dummy account for the source email address. Also note that the script can accept multiple destination email addresses.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Bugs\" /\u003eBugs\u003c/h4\u003e\u003c/div\u003e\u003cdiv\u003ePlease report bugs to \u003ca href\u003d\"mailto:hartmanng@chromium.org\"\u003ehartmanng@chromium.org\u003c/a\u003e. Feedback, features requests, and suggestions are also welcome.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8649171594513493687"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/gpu-wrangling/check_gpu_bots-script"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3043262643730806746"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3043262643730806746"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3043262643730806746"}],"author":[{"name":{"$t":"Glenn Hartmann"},"email":{"$t":"hartmanng@chromium.org"}}],"sites$pageName":{"$t":"check_gpu_bots-script"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6705022471767263703"},"published":{"$t":"2014-09-19T16:30:55.041Z"},"updated":{"$t":"2014-09-22T19:20:05.946Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-22T19:20:05.931Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"check_gpu_bots.py"},"summary":{},"content":{"type":"text/x-python","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6705022471767263703"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3043262643730806746"},{"rel":"alternate","type":"text/x-python","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/gpu-wrangling/check_gpu_bots-script/check_gpu_bots.py"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6705022471767263703"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6705022471767263703"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6705022471767263703"},{"rel":"edit-media","type":"text/x-python","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6705022471767263703"}],"author":[{"name":{"$t":"Glenn Hartmann"},"email":{"$t":"hartmanng@chromium.org"}}],"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7530530688206776362"},"published":{"$t":"2014-09-19T17:13:59.729Z"},"updated":{"$t":"2014-09-19T17:13:59.890Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-19T17:13:59.729Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"mac ubercomp.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7530530688206776362"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7345692127801460101"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/chromium-graphics/mac-delegated-rendering/mac%20ubercomp.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7530530688206776362"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7530530688206776362"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7530530688206776362"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7530530688206776362"}],"author":[{"name":{"$t":"danakj chromium"},"email":{"$t":"danakj@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2685918431525478974"},"published":{"$t":"2014-09-19T17:13:56.720Z"},"updated":{"$t":"2014-09-19T17:13:56.761Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-19T17:13:56.720Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"aura ubercomp.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2685918431525478974"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7345692127801460101"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/chromium-graphics/mac-delegated-rendering/aura%20ubercomp.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2685918431525478974"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2685918431525478974"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2685918431525478974"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2685918431525478974"}],"author":[{"name":{"$t":"danakj chromium"},"email":{"$t":"danakj@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Wil7JmA_\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2934567373974236984"},"published":{"$t":"2011-06-03T21:51:28.910Z"},"updated":{"$t":"2014-09-17T20:53:38.945Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-17T20:53:37.557Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Samsung Series 5 Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eEntering Developer Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-switch\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eDeveloper switch\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-mode-BIOS\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eDeveloper-mode BIOS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-going-on-here-\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eWhat's going on here?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-boot-your-own-image-from-USB\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eHow to boot your own image from USB\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-install-your-own-Chromium-OS-image-on-your-SSD\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHow to install your own Chromium OS image on your SSD\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving-Developer-Mode\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eLeaving Developer Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-One-other-thing-to-try-first\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eOne other thing to try first\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-use-the-Recovery-Mode-button\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eHow to use the Recovery Mode button\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-hard-reset-the-EC\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eHow to hard-reset the EC\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e9 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e9.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\nThis page contains information about the \u003ca href\u003d\"http://www.samsung.com/us/computer/chromebook\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eSamsung Series 5 Chromebook\u003c/a\u003e\r\n that is interesting and/or useful to software developers.  For general \r\ninformation about getting started with developing on Chromium OS (the \r\nopen-source version of the software on Chrome OS devices), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Entering-Developer-Mode\" /\u003eEntering Developer Mode\u003c/h2\u003e\r\nYou might want to enter developer mode if you're following the instructions in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e, or if you just want to get access to a shell on your device to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device\"\u003epoke around\u003c/a\u003e. \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware\u003c/span\u003e\u003c/b\u003e\u003cb style\u003d\"font-size:10pt\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e, software or security\u003c/span\u003e\u003c/b\u003e\u003cb style\u003d\"font-size:10pt\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e issues and may void warranty.\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003eDeveloper mode on the Samsung Series 5 has two levels of access, \"dev-switch on\" and \"dev-mode BIOS\".  With the first level you enable a command line shell, which lets you look around inside the GNU/Linux operating system, but does not let you run your own versions. The second level of access installs a special BIOS component that provides the ability to boot your own operating systems from either removable (USB/SD) or fixed (SSD) drives. Both levels of access are completely reversible, so don't be afraid to experiment.\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-switch\" /\u003eDeveloper switch\u003c/h3\u003e\r\nThe developer switch enables the command line shell. The switch is behind a little door on the right-hand side of the chromebook. To enable the developer switch you open the door, use something pointy to move the switch towards the back of the device, and reboot. \u003cspan style\u003d\"color:rgb(255,0,0)\"\u003eNote: \u003c/span\u003e\u003cb style\u003d\"color:rgb(255,0,0)\"\u003ebe gentle\u003c/b\u003e\u003cspan style\u003d\"color:rgb(255,0,0)\"\u003e!\u003c/span\u003e Some people have reported that the developer switch breaks easily.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThe first time you reboot after turning the developer switch on, your chromebook will:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eShow\r\n a scary warning that its software cannot be trusted, since a command line shell is enabled (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003eErase\r\n all personal data on the \"stateful partition\" (i.e., user accounts and \r\nsettings - no worries, though, since all data is in the cloud!).\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eMake you wait between 5 and 10 minutes while it erases the data.\u003cbr /\u003e\r\n\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\nThe erase and wait steps only happen when you first enable the developer switch, to help prevent someone from quickly reimaging your device while \r\nyou're away from the keyboard. Successive boots will:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eShow the same scary warning (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eContinue to boot only Google-signed images, and only from the SSD.\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eAt this point, verified boot is still active but because a command line shell is enabled, your system is \u003cb\u003eNOT\u003c/b\u003e secure. Refer to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device\"\u003ePoking around your Chrome OS Notebook\u003c/a\u003e to see how to access the command line shell. The message displayed at the shell itself should tell you how to set your own password to protect shell access and make your system secure again.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nHere's a photo showing the location of the developer switch:\u003cbr /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\" /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin:5px auto 0pt;display:block;text-align:center\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/b.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"171\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1307383167559/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/b.jpg\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-mode-BIOS\" /\u003eDeveloper-mode BIOS\u003c/h3\u003e\r\nIf you want to make modifications to the Chrome OS filesystem or boot your own version of Chromium OS, you'll need to activate the second level of developer access. You do this by running a special command from the command line shell, available after the device boots to the 'select language' screen by pressing Ctrl-Alt-\"→\" (Ctrl-Alt-F2). You first log in with the username 'chronos' (if you've set a shell password, you'll be prompted for it). Then you switch to the 'root' account, and run the command to install the developer-mode BIOS. For example:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003elocalhost login: \u003cb\u003echronos\u003c/b\u003e\u003cbr /\u003e\r\nchronos@localhost $ \u003cb\u003esudo bash\u003c/b\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"color:rgb(204,0,0)\"\u003elocalhost\u003c/span\u003e \u003cspan style\u003d\"color:rgb(0,0,255)\"\u003echronos #\u003c/span\u003e \u003cb\u003echromeos-firmwareupdate --mode\u003dtodev\u003c/b\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-What-s-going-on-here-\" /\u003eWhat's going on here?\u003c/h3\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified boot\u003c/a\u003e is the process by which Chrome OS ensures that you are running only the software that shipped with your chromebook. The process starts with the read-only BIOS, which is built into the device at the factory and can't be modified without disassembly (please don't try that; you'll void your warranty). The read-only BIOS verifies one of two read-write BIOSes (there are two so we can provide updates if we have to with less risk of failure) and continues execution there. The read-write BIOS then verifies one of two (same reason) kernels and executes that, and the kernel verifies its root filesystem as each block is read off the SSD.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThe normal read-write BIOSes will only boot Google-signed kernels, and only from the SSD. When you run the chromeos-firmwareupdate command above, you are replacing the primary read-write BIOS with a different one that will allow any self-signed kernel (refer to the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e) to boot from either a removable device (by pressing Ctrl-U at the scary boot screen) or from the SSD (press Ctrl-D or wait 30 seconds).\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-boot-your-own-image-from-USB\" /\u003eHow to boot your own image from USB\u003c/h2\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eFollow the steps above to turn on the developer switch and to install the developer-mode BIOS.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eBuild a Chrome OS image using the steps in the \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\" style\u003d\"font-family:arial,sans-serif\"\u003eChromium OS Developer Guide\u003c/a\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e. It does not need to be a recovery image.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eInsert the removable drive containing your image into either USB slot.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eReboot, and when you see the blue scary boot screen, press Ctrl-U.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eIt should boot your image. If for some reason it doesn't think your image is valid it will just beep once instead.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-install-your-own-Chromium-OS-image-on-your-SSD\" /\u003eHow to install your own Chromium OS image on your SSD\u003c/h2\u003e\r\nIf you follow the full instructions from the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e, you will eventually end up with a bootable USB drive containing your image. You can boot that image directly from the USB drive as described above. Since it's your personal image, it should have shell access enabled. Log in as user \"chronos\" and run\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\u003ccode\u003e/usr/sbin/chromeos-install\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nThat will wipe the SSD and install your image on it instead. When you reboot, it should attempt to boot your version. You'll still continue to see the scary boot screen at every boot, of course, as long as you are in developer mode and have the developer-mode BIOS installed, so you'll need to press Ctrl-D or wait 30 seconds to boot.\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Leaving-Developer-Mode\" /\u003eLeaving Developer Mode\u003c/h2\u003e\r\nTo leave developer mode, simply flip the developer-mode switch back to the OFF position and reboot. One of two things will happen. If your chromebook still has a valid read-write normal-mode BIOS, Google-signed kernel, and an unmodified Chrome OS root filesystem, then that's what will boot and you'll be back running the official Chrome OS image. Or, if you've modified any part of the verified boot chain so that a full verified boot process isn't possible, you'll be dropped into \u003ca href\u003d\"http://www.google.com/chromeos/recovery\"\u003erecovery mode\u003c/a\u003e. That will require you to create a bootable USB key to restore your chromebook to its fresh-from-the-factory state. That's annoying, but not dangerous. As long as you haven't taken the device apart, you shouldn't be able to permanently break anything.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nIn either case, all personal information will be wiped from the device during the transition.\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-One-other-thing-to-try-first\" /\u003eOne other thing to try first\u003c/h3\u003e\r\nWhen the developer switch is on, the BIOS is not updated by any automatic Chrome OS updates. If you don't think you changed anything but you still end up in recovery mode, it may be that you've haven't applied a pending firmware update. Turn the developer switch back on, reboot, and from a root shell run\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003echromeos-firmwareupdate --mode tonormal\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nThat will restore the primary read-write BIOS to normal mode, which may restore the verified boot process. Turn the developer switch off again and reboot. If you still end up in recovery mode, you'll just have to use the recovery process to fix it.\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-use-the-Recovery-Mode-button\" /\u003eHow to use the Recovery Mode button\u003c/h2\u003e\r\n\u003cp\u003e\r\nRecovery mode is a special boot operation in which the BIOS will:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eRefuse to boot from the SSD\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003ePrompt you to insert a recovery USB drive\u003c/li\u003e\r\n\u003cli\u003eOnly boot a Google-signed image from the USB drive\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003e\r\nYou\r\n will encounter recovery mode when the BIOS is unable to find a valid \r\nkernel to boot, either because the SSD has become corrupted or (more \r\nlikely) because you modified all the kernel partitions while in \r\ndeveloper mode and have switched back to normal mode. While in developer\r\n mode, you will be presented with the scary boot screen at every boot. \r\nPressing SPACE or RETURN will take you to recovery mode.\u003c/p\u003e\r\n\u003cp\u003e\r\nYou can also force your chromebook into recovery mode (even in normal mode) by using the recovery mode button. On the bottom of the Samsung Series 5, on the corner nearest the developer switch, there is a tiny pinhole:\u003c/p\u003e\r\n\u003cp style\u003d\"display:block;margin-right:auto;margin-left:auto;text-align:center\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/cc.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"300\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1307394806864/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/cc.jpg\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/p\u003e\r\n\u003cp\u003e\r\nIf you stick a paperclip into this hole, you'll feel it press a button. \r\nTo force recovery mode, turn the device off, press this button, and while\r\n keeping it pressed, turn the device on again. This sometimes requires \r\nthree hands or a bit of contortion, but you'll know it worked when you \r\nsee the recovery screen instead of booting normally.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-hard-reset-the-EC\" /\u003eHow to hard-reset the EC\u003c/h2\u003e\r\n\u003cp\u003e\r\nYou should never have to do this. If you think you need to and haven't been specifically instructed to do so by Google or Samsung, please contact one of those companies to tell them why.\u003c/p\u003e\r\n\u003cp\u003e\r\nThe Samsung Series 5, like most portable computers, has a small embedded controller (\"EC\") inside it that controls things like battery charging, LEDs, fans, and so forth even when the device is turned off. The EC runs anytime that power is available, even battery power. In the extremely rare and unusual case that the EC needs to be reset, the only certain way is to remove power. But since the Samsung Series 5 battery is not removable, there is a battery disconnect button for this purpose. Unplug the AC, flip the device over, and use a paperclip to gently press the battery reset button through the hole on the back of the chromebook. Hold it down for a few seconds, then release it.\u003c/p\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\r\n\u003cp\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex_reset.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"300\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1311804990465/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex_reset.jpg\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/p\u003e\r\n\u003cdiv style\u003d\"text-align:left\"\u003e\r\n\u003cp\u003e\r\nThis process turns the battery off.  It won't turn on again until you've connected the AC power cord and the EC has booted. After that, things should work normally again. You may have to press the power button once or twice, since the EC may take a moment or two to fully reboot.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eSee the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/h2c-firmware\"\u003eH2C firmware page\u003c/a\u003e for more details.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eDisassembly\u003c/span\u003e\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center.  Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first. \u003cspan style\u003d\"font-size:10pt\"\u003eIf you just want to see what the inside looks like, gaze upon this (click for a high res version):\u003c/span\u003e\u003c/p\u003e\r\n\u003cp style\u003d\"text-align:center\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex-bottom-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"236\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1363057761283/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex-bottom-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex-bottom-guts-no-battery.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"236\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1363057853361/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex-bottom-guts-no-battery.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex-top-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"190\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1363095081962/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook/alex-top-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\u003cp\u003eHowever, we acknowledge that some people like to tinker.  So here's a quick guide to taking it apart:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cul\u003e\u003cli /\u003e\r\n\u003cli\u003eFirst, acquire the necessary tools:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e1 phillips head screw driver\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eA PH0 should handle most screws\u003c/li\u003e\r\n\u003cli\u003eA J0 might be better for the screws holding the battery (if you want to remove it)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e1 wide flat head screw driver, or a butter knife\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eShut the system down and close the lid\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eFlip the laptop over so the bottom is facing up\u003c/li\u003e\r\n\u003cli\u003eRemove the three visible screws from the bottom of the case\u003c/li\u003e\r\n\u003cli\u003eRemove the rubber feet from the bottom of the case\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWorks better if you have fingernails as you can slide them under the edge and then peel up\u003c/li\u003e\r\n\u003cli\u003eConsider sticking them to the case near their original holes so they still function as grips on tables\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove the four screws that were under the rubber feet\u003c/li\u003e\r\n\u003cli\u003eStarting at one of the front corners, use your fingernails to pry apart the case slightly\u003c/li\u003e\r\n\u003cli\u003eAs you pry it apart, wiggle it a bit so the plastic clips separate cleanly rather than break apart\u003c/li\u003e\r\n\u003cli\u003eWork your way from one front corner to the other front corner\u003c/li\u003e\r\n\u003cli\u003eWork your way along the sides towards the hinge\u003c/li\u003e\r\n\u003cli\u003eOnce only the hinge side is still together, you can pull up carefully and then pull the bottom away from the hinge\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eYou'll see that only one of the components are replaceable:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eThe hard drive is a 16GiB mSATA\u003c/li\u003e\u003c/ul\u003eA now-obsolete 40-pin \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eservo connector\u003c/a\u003e may be present on some boards.\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2934567373974236984"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7762381182101003415/2"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2934567373974236984"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2934567373974236984"}],"author":[{"name":{"$t":"Bill Richardson"},"email":{"$t":"wfrichar@chromium.org"}}],"sites$pageName":{"$t":"samsung-series-5-chromebook"},"sites$revision":{"$t":"33"}},{"gd$etag":"\"WSl7JmA4\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},"published":{"$t":"2012-06-06T04:33:58.694Z"},"updated":{"$t":"2014-09-17T20:44:05.270Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-17T20:44:04.167Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Samsung Series 5 550 Chromebook and Series 3 Chromebox"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction1\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eEntering\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-going-on-here-\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eWhat's going on here?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-USB-Boot\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eUSB Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Legacy-Boot\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003eLegacy Boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving\"\u003e\u003cstrong\u003e2.6 \u003c/strong\u003eLeaving\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-boot-your-own-image-from-USB\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eHow to boot your own image from USB\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-install-your-own-Chromium-OS\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHow to install your own Chromium OS image on your SSD\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-use-the-Recovery-Mode-button\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eHow to use the Recovery Mode button\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Enabling-VMX-Support\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eEnabling VMX Support\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e8.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Samsung-Series-5-550-Chromebook-lumpy-\"\u003e\u003cstrong\u003e8.2 \u003c/strong\u003eSamsung Series 5 550 Chromebook (lumpy)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Samsung-Series-3-Chromebox-stumpy-\"\u003e\u003cstrong\u003e8.3 \u003c/strong\u003eSamsung Series 3 Chromebox (stumpy)\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cdiv\u003eThis page contains information about the \u003ca href\u003d\"http://www.samsung.com/us/computer/chrome-os-devices/all-products\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eSeries 5 550 Chromebook and the Series 3 Chromebox\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on Chrome OS devices), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Introduction1\" /\u003eIntroduction\u003c/h3\u003e\r\n\u003cp\u003eEnabling Developer mode is the first step to tinkering with your Chromebook. With Developer mode enabled you can do things like poke around on a command shell (as root if you want), install Chromium OS, or try other OS's. Note that Developer mode turns off some security features like verified boot and disabling the shell access. If you want to browse in a safer, more secure way, leave Developer mode turned OFF. Note: Switching between Developer and Normal (non-developer) modes will remove user accounts and their associated information from your Chromebook.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Entering\" /\u003eEntering\u003c/h3\u003e\r\n\u003cp\u003e\r\nThe developer switch enables the command line shell and deactivates part of the verified boot process. The switch on both devices is located \u003cb\u003einside\u003c/b\u003e the Kensington lock hole, and can be operated with a small paperclip (be gentle). To enable developer mode, simply move the switch and reboot.\u003c/p\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin:5px auto 0px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-dev-switch.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"lumpy dev switch\" border\u003d\"0\" height\u003d\"132\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1340655161694/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-dev-switch.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \u003cimg alt\u003d\"stumpy dev switch\" border\u003d\"0\" height\u003d\"133\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1340657663552/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-dev-switch.jpg\" width\u003d\"320\" /\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003e\r\nThe first time you reboot after turning the developer switch on, your chromebook will:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003eShow a scary warning that its software cannot be trusted (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003eErase all personal data on the \"stateful partition\" (i.e., user accounts and settings - no worries, though, since all data is in the cloud!).\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003eMake you wait between 5 and 10 minutes while it erases the data.\u003cbr /\u003e\r\n\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003e\r\nThe erase and wait steps only happen when you first enable the developer switch, to help prevent someone from quickly reimaging your device while you're away from the keyboard. Successive boots will:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003eShow the same scary warning (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cb style\u003d\"font-style:normal\"\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eBoot from any self-signed image on its SSD, negating the security of verified boot.\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"margin-top:5px;margin-right:auto;margin-bottom:0pt;text-align:left\" /\u003e\r\n\u003cdiv style\u003d\"text-align:left\" /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-What-s-going-on-here-\" /\u003eWhat's going on here?\u003c/h3\u003e\r\n\u003cp\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified boot\u003c/a\u003e is the process by which Chrome OS ensures that you are running only the software that shipped with your device. The process starts with the read-only BIOS, which is built into the device at the factory and can't be modified without disassembly (please don't try that; you'll void your warranty). The read-only BIOS verifies one of two read-write BIOSes (there are two so we can provide updates if we have to with less risk of failure) and continues execution there. The read-write BIOS then verifies one of two (same reason) kernels and executes that, and the kernel verifies its root filesystem as each block is read off the SSD.\u003c/p\u003e\r\n\u003cp\u003e\r\nIn Normal mode, the read-write BIOSes will only boot Google-signed kernels, and only from the SSD. In Developer mode, the BIOS allows any self-consistent kernel to boot. The BIOS displays the scary boot screen at each boot so that you will be aware that this is happening.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-USB-Boot\" /\u003eUSB Boot\u003c/h3\u003e\r\n\u003cp\u003eBy default, USB booting is disabled. Once you are in Dev-mode and have a root shell, you can run:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e# You only need to run this command once per system.\u003cbr /\u003e\r\nchromeos-firmwareupdate --mode\u003dtodev\u003cbr /\u003e\r\nsudo crossystem dev_boot_usb\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eand reboot once to boot from USB drives with Ctrl-U.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Legacy-Boot\" /\u003eLegacy Boot\u003c/h3\u003e\r\n\u003cp\u003eSorry, but this device does not support a legacy BIOS mode. It predates the launch of that feature and it is not feasible to produce updates of devices in the field.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Leaving\" /\u003eLeaving\u003c/h3\u003e\r\n\u003cp\u003eTo leave developer mode, simply flip the developer-mode switch back to the OFF position and reboot. One of two things will happen. If your Chromebook or Chromebox still has a valid read-write BIOS, Google-signed kernel, and an unmodified Chrome OS root filesystem, then that's what will boot and you'll be back running the official Chrome OS image. Or, if you've modified any part of the verified boot chain so that a full verified boot process isn't possible, you'll be dropped into \u003ca href\u003d\"http://www.google.com/chromeos/recovery\"\u003erecovery mode\u003c/a\u003e. That will require you to create a bootable USB key to restore your chromebook to its fresh-from-the-factory state. That's annoying, but not dangerous. As long as you haven't taken the device apart, you shouldn't be able to permanently break anything.\u003c/p\u003e\r\n\u003cp\u003eIn either case, all personal information will be wiped from the device during the transition.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-boot-your-own-image-from-USB\" /\u003eHow to boot your own image from USB\u003c/h2\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eBuild a Chrome OS image using the steps in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e. It does not need to be a recovery image.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eTurn on the developer switch and reboot to enter developer mode.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf this is your first time to run developer mode, remember to type \u003ccode\u003echromeos-firmwareupdate --mode\u003dtodev\u003c/code\u003e\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eAt a root shell, run \u003ccode\u003ecrossystem dev_boot_usb\u003d1\u003c/code\u003e\u003c/span\u003e, and power off.\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eInsert the removable drive containing your image into a USB slot.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003ePower on, and when you see the blue scary boot screen, press Ctrl-U.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eIt should boot your image. If for some reason it doesn't think your image is valid it will just beep once instead.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-install-your-own-Chromium-OS\" /\u003eHow to install your own Chromium OS image on your SSD\u003c/h2\u003e\r\n\u003cp\u003e\r\nIf you follow the full instructions from the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e, you will eventually end up with a bootable USB drive containing your image. You can boot that image directly from the USB drive as described above. Since it's your personal image, it should have shell access enabled. Log in as user \"chronos\" and run\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\u003ccode\u003e/usr/sbin/chromeos-install\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003e\r\nThat will wipe the SSD and install your image on it instead. When you reboot, it should attempt to boot your version. You'll still continue to see the scary boot screen at every boot as long as you are in developer mode, so you'll need to press Ctrl-D or wait 30 seconds to boot each time.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-One-other-thing-to-try-first\" /\u003e\u003c/h3\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-use-the-Recovery-Mode-button\" /\u003eHow to use the Recovery Mode button\u003c/h2\u003e\r\n\u003cp\u003e\r\nRecovery mode is a special boot operation in which the BIOS will:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003eRefuse to boot from the SSD\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003ePrompt you to insert a recovery USB drive\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eOnly boot a Google-signed image from the USB drive\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003e\r\nYou will encounter recovery mode when the BIOS is unable to find a valid kernel to boot, either because the SSD has become corrupted or (more likely) because you modified all the kernel partitions while in developer mode and have switched back to normal mode. While in developer mode, you will be presented with the scary boot screen at every boot. Pressing SPACE or RETURN will take you to recovery mode.\u003c/p\u003e\r\n\u003cp\u003eYou can also force your chromebook into recovery mode (even in normal mode) by using the recovery mode button. The recovery button on the Chromebook is a tiny pinhole on the bottom, directly underneath the power button. On the Chromebox, the pinhole is on the back corner, next to the outer Display Port connector.\u003c/p\u003e\r\n\u003cdiv style\u003d\"text-align:left\" /\u003e\r\n\u003cdiv style\u003d\"text-align:center;display:block\"\u003e\r\n\u003cdiv style\u003d\"display:inline;text-align:center;margin:5px 0px 0px 10px\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-case.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"145\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1358551464660/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-case.jpg\" width\u003d\"200\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n    \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"86\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1342018298396/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cp\u003e\r\nIf you stick a paperclip into this hole, you'll feel it press a button. To force recovery mode, turn the device off, press this button, and while keeping it pressed, turn the device on again. This sometimes requires three hands or a bit of contortion, but you'll know it worked when you see the recovery screen instead of booting normally.\u003c/p\u003e\r\n\r\n\u003cp\u003eFollow the \u003ca href\u003d\"http://www.google.com/chromeos/recovery\" target\u003d\"_blank\"\u003erecovery mode instructions\u003c/a\u003e to restore your device to its factory-fresh state.\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003chr /\u003e\r\n\u003cp\u003e\r\nNote: The other pinhole on the bottom of the Series 5 550 Chromebook is the \u003cspan style\u003d\"color:rgb(34,34,34);font-family:Arial,Helvetica,sans-serif\"\u003ebattery disconnect switch. When you poke it, it disconnects the battery so that the Chromebook can be shipped from the factory and left on shelves for months without the EC running and slowly draining power. But since the battery is off, opening the lid or poking the power button won't do anything. The only way to turn the device on again is to connect the AC power, wait a second or two for the EC to boot, and then press the power button. So don't poke anything into that hole unless you have your power cord handy.\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Enabling-VMX-Support\" /\u003eEnabling VMX Support\u003c/h2\u003e\r\n\u003cp\u003eThese two devices shipped with a BIOS that hard disables VMX during the boot time.  It is possible to fix this though.  Please see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/coreboot-vmx-hack\"\u003eHacking VMX Support Into Coreboot\u003c/a\u003e guide for more information.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThese devices use \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e and \u003ca href\u003d\"http://www.denx.de/wiki/U-Boot\" rel\u003d\"nofollow\"\u003eDas U-Boot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-uboot_v2-1299.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e and the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/u-boot/+/firmware-uboot_v2-1299.B\"\u003eChromium OS u-boot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-uboot_v2-1299.B\u003c/code\u003e branches.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center.  Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first. \u003cspan style\u003d\"font-size:10pt\"\u003eIf you just want to see what the inside looks like, gaze upon this (click for high res versions):\u003c/span\u003e\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Samsung-Series-5-550-Chromebook-lumpy-\" /\u003eSamsung Series 5 550 Chromebook (lumpy)\u003c/h3\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-internals.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"233\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1371774836497/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-internals.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-internals-bare.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"233\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1359393711041/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-internals-bare.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-internals-top.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"121\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1364930759873/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/lumpy-internals-top.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\r\n\u003c/div\u003e\r\n\r\n\u003cp\u003eHowever, we acknowledge that some people like to tinker.  So here's a quick guide to taking it apart.\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eGet a phillips head screw driver and a butter knife (any similar wide/flat material will do as long as one edge is not sharp)\u003c/li\u003e\r\n\u003cli\u003eShut the system down and close the lid\u003c/li\u003e\r\n\u003cli\u003eFlip the laptop over so the bottom is facing up\u003c/li\u003e\r\n\u003cli\u003eLocate the battery disconnect and stick a paper clip in there\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eNOTE: The machine will not be able to power up again until you plug it in -- so you will need a power supply!\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove the 4 visible screws\u003c/li\u003e\r\n\u003cli\u003eRemove the 4 rubber feet and the screws under them\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eYou should start removing them starting from the edge closest to the edge of the computer as that is where the screw hole is\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eNow you will have to pull the top and bottom parts of the case apart (see below for tips)\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eBe aware that the case is held together by \u003cb\u003emany\u003c/b\u003e plastic tabs\u003c/li\u003e\r\n\u003cli\u003eEvery time you get stuck and think it might be glued/screwed together, remember it is not -- it's just \u003cb\u003emore\u003c/b\u003e plastic tabs\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eUsing your nails and butter knife, pull apart the case slight apart at one of the bottom corners (near the speakers)\u003c/li\u003e\r\n\u003cli\u003eSlip the butter knife into the small gap\u003c/li\u003e\r\n\u003cli\u003eUsing the edge of the knife that is \u003cb\u003enot\u003c/b\u003e, slide it along the front edge of the case\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eWiggle it back and forth as you go\u003c/li\u003e\r\n\u003cli\u003eGently pull on the case to pop each tab as you go\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eOnce the front edge is open, move towards the back on each side until you get to the side ports (USB/SD)\u003c/li\u003e\r\n\u003cli\u003eNow you should be able to gently pull \u0026amp; wiggle using the case itself\u003c/li\u003e\r\n\u003cli\u003eRepeat until the whole thing comes off\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eYou'll see that some of the components are replaceable:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eThe hard drive is a 16GiB mSATA\u003c/li\u003e\r\n\u003cli\u003eThere is one slot for 204-Pin DDR3 SO-DIMM laptop memory\u003c/li\u003e\r\n\u003cli\u003ePower supply: 19V \u003cimg border\u003d\"0\" height\u003d\"5\" src\u003d\"http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices/direct-current.svg?attredirects\u003d0\u0026amp;d\u003d1\" /\u003e (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Direct_current\" rel\u003d\"nofollow\"\u003eDC\u003c/a\u003e) 2.1A \u003cimg height\u003d\"12\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1364850218094/chromium-os/developer-information-for-chrome-os-devices/center-positive-polarity.svg\" /\u003e (\u003ca href\u003d\"http://en.wikipedia.org/wiki/Polarity_symbols\" rel\u003d\"nofollow\"\u003epositive polarity tip\u003c/a\u003e)\u003c/li\u003e\u003cli\u003eThe \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eservo connector\u003c/a\u003e (may not be present on most units) is a now-obsolete 1x40 connector.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Samsung-Series-3-Chromebox-stumpy-\" /\u003eSamsung Series 3 Chromebox (stumpy)\u003c/h3\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-full.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1403287280677/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-full.jpg\" width\u003d\"198\" /\u003e\u003c/a\u003e   \r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-mid.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1403287294752/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-mid.jpg\" width\u003d\"198\" /\u003e\u003c/a\u003e   \r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-bare.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1403287307654/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-bare.jpg\" width\u003d\"198\" /\u003e\u003c/a\u003e   \r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-bottom-cards.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1403287326189/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-bottom-cards.jpg\" width\u003d\"177\" /\u003e\u003c/a\u003e   \r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-bottom-bare.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1403287339202/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-bottom-bare.jpg\" width\u003d\"200\" /\u003e\u003c/a\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6032530868906671964"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"}],"author":[{"name":{"$t":"Bill Richardson"},"email":{"$t":"wfrichar@chromium.org"}}],"sites$pageName":{"$t":"samsung-sandy-bridge"},"sites$revision":{"$t":"40"}},{"gd$etag":"\"Xil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1656014237960155922"},"published":{"$t":"2013-02-05T04:03:38.911Z"},"updated":{"$t":"2014-09-17T20:34:46.058Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-17T20:34:44.601Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"HP Pavilion Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDeveloper Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat's inside?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThis page contains information about the \u003ca href\u003d\"http://www.google.com/intl/en/chrome/devices/hp-pavilion-chromebook.html\"\u003eHP Pavilion Chromebook\u003c/a\u003e that is interesting and/or useful to software developers. For general information about getting started with developing on Chromium OS (the open-source version of the software on the Chrome Notebook), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Developer-Mode\" /\u003eDeveloper Mode\u003c/h2\u003e\r\n\u003cp\u003e\u003cb\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware, software or security issues and may void warranty.\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eDetails for working with developer mode can be found \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c7-chromebook\"\u003eon this page\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eThis device uses \u003ca href\u003d\"http://www.coreboot.org/\" rel\u003d\"nofollow\"\u003ecoreboot\u003c/a\u003e and \u003ca href\u003d\"http://www.denx.de/wiki/U-Boot\" rel\u003d\"nofollow\"\u003eDas U-Boot\u003c/a\u003e to boot the system. You can find the source in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/firmware-butterfly-2788.B\"\u003eChromium OS coreboot git tree\u003c/a\u003e and the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/third_party/u-boot/+/firmware-butterfly-2788.B\"\u003eChromium OS u-boot git tree\u003c/a\u003e in the \u003ccode\u003efirmware-butterfly-2788.B\u003c/code\u003e branches.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside?\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center.  Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first. \u003cspan style\u003d\"font-size:10pt\"\u003eIf you just want to see what the inside looks like, gaze upon this (click for a high res version):\u003c/span\u003e\u003c/p\u003e\r\n\u003cdiv style\u003d\"text-align:center;display:block\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-top-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"216\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362183943375/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-top-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e   \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-bottom-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"text-align:left;font-size:10pt\"\u003e\u003cimg border\u003d\"0\" height\u003d\"198\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362184029141/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-bottom-guts.jpg\" width\u003d\"320\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\"\u003e\r\n\u003cp\u003eHowever, we acknowledge that some people like to tinker.  So here's a quick guide to taking it apart:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cul /\u003e\r\n\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eFirst, acquire the necessary tools:\u003c/span\u003e\u003c/li\u003e\r\n\u003cul\u003e\r\n\u003cul\u003e\r\n\u003cul /\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e1 phillips head screw driver (a PH0 should be able to handle everything)\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e1 wide flat head screw driver, or a butter knife\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eShut the system down and close the lid\u003c/li\u003e\r\n\u003cli\u003eFlip the laptop over so the bottom is facing up and the hinge is facing away from you\u003c/li\u003e\r\n\u003cli\u003eRemove the battery\u003c/li\u003e\r\n\u003cli\u003eRemove all screws on D-panel (see pic) w/phillips head (there are 10)\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-dpanel.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt\"\u003e\u003cimg border\u003d\"0\" height\u003d\"137\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362211848295/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-dpanel.jpg\" style\u003d\"display:block;margin-right:auto;margin-left:auto;text-align:center\" width\u003d\"200\" /\u003e\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003ePry off keyboard using a flat instrument\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThe keyboard can bend inward and upward to dislodge the tabs which are all along the top and bottom of the keyboard\u003c/li\u003e\r\n\u003cli\u003eStart at the bottom left corner and work your way up the left side\u003c/li\u003e\r\n\u003cli\u003eWith the left side popped, slide the screw driver along the middle underneath and wiggle/pop the tabs out as you go\u003c/li\u003e\r\n\u003cli\u003eThere is a ribbon cable underneath the right shift key that needs to be disconnected from the motherboard\u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:center;display:block;margin-left:auto;margin-right:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-keyboard.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt;text-align:center\"\u003e\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362212140174/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-keyboard.jpg\" width\u003d\"200\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove all screws on C-panel. Note location of \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/servo\"\u003eservo\u003c/a\u003e connector (non-standard 2x25 connector), circled in blue.\u003cbr /\u003e\r\n\u003cdiv style\u003d\"text-align:center;display:block;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-cpanel.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt;text-align:center\"\u003e\u003cimg border\u003d\"0\" height\u003d\"150\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362212239444/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-cpanel.jpg\" width\u003d\"200\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eDisconnect the two ribbon cables and pry off C-panel\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eYou can use the open holes in the metal plate to pull up until the edge along the hinge separates\u003c/li\u003e\r\n\u003cli\u003eUsing the edge along the hinge, pull the top panel away from the bottom panel\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli /\u003e\r\n\u003cli\u003eUnit is now disassembled. Note the location of the WP switch.\u003cbr /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-top-wp.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1362213847729/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook/butterfly-top-wp.jpg\" width\u003d\"150\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"http://dev.chromium.org/chromium-os/developer-information-for-chrome-os-devices/chromebook-pixel/link-bottom-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"background-color:rgb(255,255,255)\" /\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/hp-pavilion-14-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1656014237960155922"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1656014237960155922"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1656014237960155922"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"hp-pavilion-14-chromebook"},"sites$revision":{"$t":"17"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5234462539849888478"},"published":{"$t":"2012-11-30T17:05:48.863Z"},"updated":{"$t":"2014-09-17T03:58:45.028Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-17T03:58:43.707Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Focus and Activation"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eFocus and Activation are closely related.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Definitions\" /\u003eDefinitions\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eFocused window - this is the window that receives keyboard input. The focused window is always or is always contained by the Active window.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eActive window - this is the window that is rendered as key - i.e. the one that contains the focused element. Different platforms will render this differently and may show additional affordances e.g. a different treatment in the window switcher.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Notes\" /\u003eNotes\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eA \"top level\" window is a window that has no parent other than window manager constructs. Think of a Chrome window.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAn \"activatable\" window is a top level window that can be activated. Not all top level windows can be activated at any given time. For instance in Ash, if the screen is locked calling GetActivatableWindow() for a window behind the lock screen may return a window in front of the lock screen, whereas GetTopLevelWindow() will return the non-activatable toplevel behind the lock screen. For this reason GetActivatableWindow is a method most useful to the focus/activation implementation, and GetTopLevelWindow is the method most useful to general application code.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn Aura, the CoreWM library provided by Views handles focus and activation changes in the class FocusController. The FocusController implements two interfaces - aura::client::FocusClient and aura::client::ActivationClient. Every RootWindow must have an associated Focus/ActivationClient implementation associated with it, though several RootWindows can share the same implementation. For Desktop-Aura, each top level DesktopNativeWidgetAura creates a separate FocusController for the associated RootWindow. For Ash, there is a single FocusController shared by all RootWindows managed by the DisplayController.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe FocusController tracks the current active and focused windows, and sends notifications when either of these change to registered implementations of aura::client::FocusChangeObserver and aura::client::ActivationChangeObserver.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eViews also tracks focus, for views::View subclasses within a views::Widget. Think of it this way. In the Aura world, an aura::Window can have focus, and can have an embedded View hierarchy via NativeWidgetAura/Widget. Within that focused aura::Window there can be an individual View that has focus, e.g. the omnibox textfield vs. a button etc. Each toplevel views::Widget has a views::FocusManager which handles View focus. It also handles things like focus traversal. Focus traversal is what happens when you press Tab. The traversal code figures out what View to focus next when you press Tab or Shift+Tab.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen a views::Widget is deactivated, its FocusManager stores the focused view in ViewStorage for restoration later. The history behind this is somewhat vestigial but the storage/restoration step is still necessary. When the Widget is later reactivated, the last focused view is refocused. This is true in both non-Aura Win32 Views and in Aura Views.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs far as what can be focused or activated in Aura, FocusController delegates to an implementation of the FocusRules interface to determine what can be focused or activated. There are different implementations for Ash (AshFocusRules) and Desktop-Aura (DesktopFocusRules). These rules enforce specifics like not activating windows behind the lock screen, etc.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2680325264819182270"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/aura/focus-and-activation"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5234462539849888478"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5234462539849888478"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5234462539849888478"}],"author":[{"name":{"$t":"Ben Goodger"},"email":{"$t":"ben@chromium.org"}}],"sites$pageName":{"$t":"focus-and-activation"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7352488064831892909"},"published":{"$t":"2013-02-21T23:23:18.164Z"},"updated":{"$t":"2014-09-17T03:58:27.165Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-02-22T00:35:36.375Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Focus and Activation in Views and Aura"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eFocus and Activation are closely related.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Definitions\" /\u003eDefinitions\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eFocused window - this is the window that receives keyboard input. The focused window is always or is always contained by the Active window.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eActive window - this is the window that is rendered as key - i.e. the one that contains the focused element. Different platforms will render this differently and may show additional affordances e.g. a different treatment in the window switcher.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Notes\" /\u003eNotes\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eA \"top level\" window is a window that has no parent other than window manager constructs. Think of a Chrome window.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAn \"activatable\" window is a top level window that can be activated. Not all top level windows can be activated at any given time. For instance in Ash, if the screen is locked calling GetActivatableWindow() for a window behind the lock screen may return a window in front of the lock screen, whereas GetTopLevelWindow() will return the non-activatable toplevel behind the lock screen. For this reason GetActivatableWindow is a method most useful to the focus/activation implementation, and GetTopLevelWindow is the method most useful to general application code.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn Aura, the CoreWM library provided by Views handles focus and activation changes in the class FocusController. The FocusController implements two interfaces - aura::client::FocusClient and aura::client::ActivationClient. Every RootWindow must have an associated Focus/ActivationClient implementation associated with it, though several RootWindows can share the same implementation. For Desktop-Aura, each top level DesktopNativeWidgetAura creates a separate FocusController for the associated RootWindow. For Ash, there is a single FocusController shared by all RootWindows managed by the DisplayController.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe FocusController tracks the current active and focused windows, and sends notifications when either of these change to registered implementations of aura::client::FocusChangeObserver and aura::client::ActivationChangeObserver.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eViews also tracks focus, for views::View subclasses within a views::Widget. Think of it this way. In the Aura world, an aura::Window can have focus, and can have an embedded View hierarchy via NativeWidgetAura/Widget. Within that focused aura::Window there can be an individual View that has focus, e.g. the omnibox textfield vs. a button etc. Each toplevel views::Widget has a views::FocusManager which handles View focus. It also handles things like focus traversal. Focus traversal is what happens when you press Tab. The traversal code figures out what View to focus next when you press Tab or Shift+Tab.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen a views::Widget is deactivated, its FocusManager stores the focused view in ViewStorage for restoration later. The history behind this is somewhat vestigial but the storage/restoration step is still necessary. When the Widget is later reactivated, the last focused view is refocused. This is true in both non-Aura Win32 Views and in Aura Views.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs far as what can be focused or activated in Aura, FocusController delegates to an implementation of the FocusRules interface to determine what can be focused or activated. There are different implementations for Ash (AshFocusRules) and Desktop-Aura (DesktopFocusRules). These rules enforce specifics like not activating windows behind the lock screen, etc.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/focus-and-activation-in-views-and-aura"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7352488064831892909"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7352488064831892909"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7352488064831892909"}],"author":[{"name":{"$t":"Ben Goodger"},"email":{"$t":"ben@chromium.org"}}],"sites$pageName":{"$t":"focus-and-activation-in-views-and-aura"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"Wil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4228609602200658370"},"published":{"$t":"2014-04-14T22:56:16.458Z"},"updated":{"$t":"2014-09-16T23:04:25.242Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-16T23:04:23.226Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Filter Effects"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eFilter Effects in Chrome can be somewhat confusing. The \u003ca href\u003d\"http://www.w3.org/TR/SVG/filters.html\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eSVG\u003c/a\u003e and \u003ca href\u003d\"http://www.w3.org/TR/filter-effects-1/\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eCSS\u003c/a\u003e specs give us three different ways of specifying filters (SVG-on-SVG, SVG-in-CSS, shorthand CSS), Chrome has two rendering modes (GPU-accelerated or CPU), and two filter implementations (Blink and Skia). This is an attempt to document the current situation, and where we're headed.\u003c/span\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eOne important thing to note is that we currently only trigger the GPU filter path for source elements that are already in a composited layer, e.g., 2D \u0026lt;canvas\u0026gt;, WebGL, \u0026lt;video\u0026gt;, 3D CSS. We don't really have a choice but to apply these filters in the compositor, since only the compositor contains the source textures to which the filters are to be applied. We do trigger the GPU path for filters which are animated, but only for the duration of the animation, after which we switch back to software (same as is done for animated opacity, 2D transforms, etc). All other rendering of filters on web content uses the CPU. Currently, SVG-on-SVG filters are only rendered using a CPU path.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eWays to author filters (in chronological order):\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eSVG-on-SVG filters: the oldest (spec-wise, and blink-wise). Syntax: filter\u003d\"url(#foo)\" on the target SVG element, where \"foo\" refers to an SVG filter graph. Applies a SVG filter to an SVG element, via a DOM attribute. Animatable via SVG. First shipped in Chrome M6.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eSVG-in-CSS filters (aka reference filters, aka url() filters). Specified by CSS property -webkit-filter: url(#foo), where foo refers to the ID of an SVG filter node. Renders an HTML element to a buffer, then applies an SVG filter DAG to it. First appeared in Firefox 5 or so. \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eImplemented in Chrome M25 on the software path, and M31 on the GPU path (disabled in M32 due to ubercomp; re-enabled in M33).\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eAnimatable via SVG.\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eCSS shorthand filters. Specified by (e.g.,) CSS property -webkit-filter: grayscale(50%) hue-rotate(90deg). A simple linear chain of filters. This is essentially a simplified subset of what is possible with the SVG DAG. Animatable via CSS. Proposed by Apple (but first shipped in Chrome M19), shipped in Safari 6.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eThe Blink implementation uses a graph of FilterEffect nodes (in platform/graphics/filters/FilterEffect.*, and subclasses FE*.) This renders only on the CPU.\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eThe Skia implementation uses a graph of SkImageFilter nodes (in src/core/SkImageFilter.*, and subclasses *ImageFilter.cpp). This has CPU and GPU modes.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eShipping now:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ctable border\u003d\"1\" cellpadding\u003d\"0\" cellspacing\u003d\"0\" dir\u003d\"ltr\" style\u003d\"table-layout:fixed;font-family:arial,sans,sans-serif;border-collapse:collapse;border:1px solid rgb(204,204,204)\"\u003e\u003ccolgroup\u003e\u003ccol width\u003d\"100\" /\u003e\u003ccol width\u003d\"174\" /\u003e\u003ccol width\u003d\"420\" /\u003e\u003ccol width\u003d\"234\" /\u003e\u003c/colgroup\u003e\u003ctbody\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\" /\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSyntax\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eCPU\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eGPU\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSVG-on-SVG\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003efilter\u003d\"url(#foo)\"\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eFilterEffect DAG, renderer process\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003enone yet*\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSVG-in-CSS\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003e-webkit-filter: url(#foo)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eFilterEffect DAG, renderer process\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSkImageFilter DAG, compositor thread\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eCSS shorthand\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003e-webkit-filter: grayscale(50%)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eFilterEffect chain, renderer process\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSkImageFilter chain, compositor thread\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e(*there was actually a prototype implementation under the \"Accelerated SVG Filters\" flag, but it ran in the renderer process, and the resulting filtered element had to incur a readback from the GPU to be (CPU) composited. It was useful for testing the individual Skia GPU filters before we had the accelerated SVG-in-CSS path, but it's now old and busted. I've removed the flag in M36.)\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eFuture (paths which will change are in bold):\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ctable border\u003d\"1\" cellpadding\u003d\"0\" cellspacing\u003d\"0\" dir\u003d\"ltr\" style\u003d\"table-layout:fixed;font-family:arial,sans,sans-serif;border-collapse:collapse;border:1px solid rgb(204,204,204)\"\u003e\u003ccolgroup\u003e\u003ccol width\u003d\"100\" /\u003e\u003ccol width\u003d\"174\" /\u003e\u003ccol width\u003d\"420\" /\u003e\u003ccol width\u003d\"234\" /\u003e\u003c/colgroup\u003e\u003ctbody\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\" /\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSyntax\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eCPU\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eGPU\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSVG-on-SVG\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003efilter\u003d\"url(#foo)\"\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom;font-weight:bold\"\u003eSkImageFilter DAG, impl thread (enabled in M37)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom;font-weight:bold\"\u003eSkImageFilter DAG, compositor thread (enabled in M37 where Ganesh is enabled)\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSVG-in-CSS\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003e-webkit-filter: url(#foo)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom;font-weight:bold\"\u003eSkImageFilter DAG, impl thread (enabled in M39)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSkImageFilter DAG, compositor thread\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:21px\"\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eCSS shorthand\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003e-webkit-filter: grayscale(50%)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom;font-weight:bold\"\u003eSkImageFilter chain, impl thread (enabled in M39)\u003c/td\u003e\u003ctd style\u003d\"font-family:arial,sans-serif;margin:0px;padding:2px 3px;vertical-align:bottom\"\u003eSkImageFilter chain, compositor thread\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe GPU path for SVG-on-SVG filters (***) can forced on via --force-gpu-rasterization (the Ganesh GPU rasterization path, essentially).\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003eNow that these changes are done, all software rasterization of filters is be performed on the impl-thread using the Skia implementation, and compatible with multi-threaded and GPU rasterization. The Blink implementation of filter processing can be removed (including its bespoke ParallelJobs threading library). As a side note, this will also make filters compatible with non-tiled GPU-accelerated rendering of web content too (a la IE9+), if that proves promising.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/image-filters"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4228609602200658370"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4228609602200658370"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4228609602200658370"}],"author":[{"name":{"$t":"danakj chromium"},"email":{"$t":"danakj@chromium.org"}}],"sites$pageName":{"$t":"image-filters"},"sites$revision":{"$t":"13"}},{"gd$etag":"\"Wil7JmA_\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7065492440810770218"},"published":{"$t":"2014-02-21T01:23:25.308Z"},"updated":{"$t":"2014-09-16T13:21:33.560Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-16T13:21:33.544Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Jinja"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eOverview\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Factoring-code\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eFactoring code\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Filters\"\u003e\u003cstrong\u003e1.1.1 \u003c/strong\u003eFilters\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Jinja-environment\"\u003e\u003cstrong\u003e1.1.2 \u003c/strong\u003eJinja environment\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Style\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eStyle\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Python-Jinja-split\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003ePython/Jinja split\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Do-not-call-Python-functions-from-Jinja-except-custom-filters-\"\u003e\u003cstrong\u003e2.1.1 \u003c/strong\u003eDo not call Python functions from Jinja (except custom filters)\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Python\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003ePython\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-One-dictionary-display-per-context-inline-expressions\"\u003e\u003cstrong\u003e2.2.1 \u003c/strong\u003eOne dictionary display per context, inline expressions\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Logic-and-local-variables-before-display\"\u003e\u003cstrong\u003e2.2.2 \u003c/strong\u003eLogic and local variables before display\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Separate-functions-if-necessary\"\u003e\u003cstrong\u003e2.2.3 \u003c/strong\u003eSeparate functions if necessary\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Early-return-if-necessary\"\u003e\u003cstrong\u003e2.2.4 \u003c/strong\u003eEarly return if necessary\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Jinja\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eJinja\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Keep-it-simple\"\u003e\u003cstrong\u003e2.3.1 \u003c/strong\u003eKeep it simple\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Spacing\"\u003e\u003cstrong\u003e2.3.2 \u003c/strong\u003eSpacing\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-set-if-simple-and-used-in-only-one-place\"\u003e\u003cstrong\u003e2.3.3 \u003c/strong\u003eset if simple and used in only one place\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Variables-should-be-complete-words-not-fragments\"\u003e\u003cstrong\u003e2.3.4 \u003c/strong\u003eVariables should be complete words, not fragments\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Name-variables-after-default-value\"\u003e\u003cstrong\u003e2.3.5 \u003c/strong\u003eName variables after default value\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Comment-end-of-long-blocks\"\u003e\u003cstrong\u003e2.3.6 \u003c/strong\u003eComment end of long blocks\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Use-implicit-False\"\u003e\u003cstrong\u003e2.3.7 \u003c/strong\u003eUse implicit False\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Whitespace\"\u003e\u003cstrong\u003e2.3.8 \u003c/strong\u003eWhitespace\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Treat-multi-line-macros-as-blocks-indent-trailing-semicolon-in-macro-\"\u003e\u003cstrong\u003e2.3.9 \u003c/strong\u003eTreat multi-line macros as blocks (indent, trailing semicolon ; in macro)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Treat-one-line-macros-as-in-line-no-indent---to-strip-trailing-linebreak-semicolon-at-call-site-\"\u003e\u003cstrong\u003e2.3.10 \u003c/strong\u003eTreat one-line macros as in-line (no indent, {%- to strip trailing linebreak, semicolon ; at call site)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-C-code-generation\"\u003e\u003cstrong\u003e2.3.11 \u003c/strong\u003eC++ code generation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Don-t-mix-Jinja-templates-and-C-templates\"\u003e\u003cstrong\u003e2.3.12 \u003c/strong\u003eDon't mix Jinja templates and C++ templates\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Group-related-code-minimize-code-within-clauses\"\u003e\u003cstrong\u003e2.3.13 \u003c/strong\u003eGroup related code, minimize code within clauses\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Tips\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eTips\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Syntax-highlighting\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eSyntax highlighting\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-vim\"\u003e\u003cstrong\u003e3.1.1 \u003c/strong\u003evim\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Emacs\"\u003e\u003cstrong\u003e3.1.2 \u003c/strong\u003eEmacs\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Performance\"\u003e\u003cstrong\u003e4 \u003c/strong\u003ePerformance\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-External-links\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eExternal links\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ca href\u003d\"http://jinja.pocoo.org/\" rel\u003d\"nofollow\"\u003eJinja\u003c/a\u003e is a \u003ca href\u003d\"http://en.wikipedia.org/wiki/Template_language\" rel\u003d\"nofollow\"\u003etemplate engine\u003c/a\u003e for Python, which is used in a number of places in Chromium, particularly for generating bindings. It's also referred to as Jinja2, as it's on its second major version. Usage is generally easy, but it's a new macro language to learn, and a few tips can help.\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003ci\u003eWarning:\u003c/i\u003e\u003c/b\u003e make sure to list Jinja template files as \u003ccode\u003einputs\u003c/code\u003e in the appropriate \u003ccode\u003e.gyp\u003c/code\u003e or \u003ccode\u003e.gypi\u003c/code\u003e file, just like the Python files that use them – they \u003ci\u003eare\u003c/i\u003e source code – otherwise the generated files will not rebuild properly.\u003cbr /\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNotable uses:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/mojo/public/tools/bindings/\"\u003emojo/public/tools/bindings/\u003c/a\u003e: Mojo bindings for C++, Python, Java, JavaScript\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py\" style\u003d\"background-color:transparent;font-size:10pt\"\u003eSource/bindings/scripts/code_generator_v8.py\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e : \u003c/span\u003eBlink V8 bindings (\u003ca href\u003d\"http://www.chromium.org/developers/design-documents/idl-compiler\"\u003eIDL compiler\u003c/a\u003e)\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/build/scripts/template_expander.py\" style\u003d\"background-color:transparent;font-size:10pt\"\u003eSource/build/scripts/template_expander.py\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e : general templates in Blink build\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h2\u003e\r\n\u003cdiv\u003e\u003ci\u003eSee: \u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/\" rel\u003d\"nofollow\"\u003eTemplate Designer Documentation\u003c/a\u003e\u003c/i\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eJinja templates provide both basic string substitution (fill in the blank, as in Python \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"http://docs.python.org/2/library/string.html#template-strings\" rel\u003d\"nofollow\"\u003etemplate strings\u003c/a\u003e) and more advanced programming facilities. Key features are as follows:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#if\" rel\u003d\"nofollow\"\u003e\u003ccode\u003eif\u003c/code\u003e\u003c/a\u003e (conditional): \u003ccode\u003e{% if %}...{% elif %}...{% else %}...{% endif %}\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#for\" rel\u003d\"nofollow\"\u003e\u003ccode\u003efor\u003c/code\u003e\u003c/a\u003e (definite iteration): \u003ccode\u003e{% for i in l if i.foo %}...{% endfor %}\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\r\nNote that linebreaks are \u003ci\u003enot\u003c/i\u003e meaningful in Jinja block control statements, so you can put linebreaks wherever convenient, and don't need to use \u003ccode\u003e()\u003c/code\u003e for implicit line continuation.\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#macros\" style\u003d\"font-size:10pt\" rel\u003d\"nofollow\"\u003eMacros\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e: Macros are actually functions (evaluation semantics, not expansion semantics: they are evaluated as a function, not expanded in place like a macro). However, they can be called with the current evaluation environment (\"context\"), which results in dynamic binding, with results like actual macros; see \u003c/span\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#import-context-behavior\" rel\u003d\"nofollow\"\u003eImport Context Behavior\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e. Macros are suitable for \u003ci\u003eproducing\u003c/i\u003e text, but filters are clearer for \u003ci\u003etransforming\u003c/i\u003e text, notably simple inline transforms (like changing capitalization) or wrapping or indenting a block of text.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#block\" rel\u003d\"nofollow\"\u003eBlocks\u003c/a\u003e: Blocks are a bit trickier to use than macros, and are generally used like actual macros (by default calling environment is visible). They are powerful in general use, letting you have multiple templates based off of a base template, but in code generators, t\u003c/span\u003ehey are \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003emostly used when you want to optionally include or omit a block of code, and don't want to specify arguments (not a parametrized function, just a block that uses the current environment). If you always want to include code, a macro is easier, and if you want to specify arguments, a macro is clearer.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eOthers:\u003c/span\u003e\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#assignments\" rel\u003d\"nofollow\"\u003eset\u003c/a\u003e (assignment): \u003ccode\u003e{% set x \u003d '' %}\u003c/code\u003e particularly useful with conditional expression: \u003ccode\u003e{% set x \u003d 'foo' if foo else 'bar' %}\u003c/code\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eIn rare cases \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003ecall\u003c/code\u003e is useful, but usually a custom filter works and is clearer.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNote that Jinja identifiers are \u003cb\u003elowercase,\u003c/b\u003e and thus the 3 \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#literals\" rel\u003d\"nofollow\"\u003eliteral\u003c/a\u003e constants are written \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003etrue, false, none\u003c/code\u003e, unlike in Python.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Factoring-code\" /\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eFactoring code\u003c/span\u003e\u003c/h3\u003e\r\n\u003cdiv\u003eMacros can be put into a library and then imported into the template that uses them. This should generally be done (even for simple macros or those used in only one file), so that the code (macros) are separate from the data (template), and the actual template looks like the output, without being cluttered with macro definitions. This also allows you to have whitespace between macro definitions in the library.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eTo put macros into a library, just put them into another file and import them with an \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#import\" rel\u003d\"nofollow\"\u003e\u003ccode\u003eimport\u003c/code\u003e\u003c/a\u003e statement. In terms of name binding, you often want macros to access the global environment \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e– so you don't need to pass everything explicitly as an argument, and to simplify factoring code into a macro \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e– which you can do via the \u003ccode\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#import-context-behavior\" rel\u003d\"nofollow\"\u003ewith context\u003c/a\u003e\u003c/code\u003e keywords,\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eFactoring code using blocks is a bit trickier, since you need to use \u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#template-inheritance\" style\u003d\"background-color:transparent;font-size:10pt\" rel\u003d\"nofollow\"\u003etemplate Inheritance\u003c/a\u003e, specifically one base template with the block layout, and a derived template that fills in values for the block. \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eSee \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003einterface_base.cpp\u003c/code\u003e and \u003ccode\u003einterface.cpp\u003c/code\u003e in the V8 bindings code generator for example of using blocks and template inheritance.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Filters\" /\u003eFilters\u003c/h4\u003e\r\n\u003cdiv\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#filters\" rel\u003d\"nofollow\"\u003eFilters\u003c/a\u003e are very useful for transforming text functionally in Jinja, and can simplify code significantly. There are many \u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#builtin-filters\" rel\u003d\"nofollow\"\u003ebuiltin filters\u003c/a\u003e, often with powerful features, and you can write \u003ca href\u003d\"http://jinja.pocoo.org/docs/api/#writing-filters\" rel\u003d\"nofollow\"\u003ecustom filters\u003c/a\u003e. In terms of use, you can either apply filters to variables, either in an expression expansion \u003ccode\u003e{{ ... }}\u003c/code\u003e or in a block control statement \u003ccode\u003e{% ... %}\u003c/code\u003e, or create a \u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#id7\" rel\u003d\"nofollow\"\u003efilter section\u003c/a\u003e to apply a filter to a portion of the template via \u003ccode\u003e{% filter ... %}...{% endfilter %}\u003c/code\u003e.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eParticularly useful filters for expression expansion include:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#indent\" rel\u003d\"nofollow\"\u003eindent\u003c/a\u003e:\u003c/code\u003e \u003ccode\u003eindent, indent(8), indent(8, true)\u003c/code\u003e – very useful for nested code via multi-line macros; see above.\u003c/li\u003e\r\n\u003cli\u003e\u003ccode\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#join\" rel\u003d\"nofollow\"\u003ejoin\u003c/a\u003e:\u003c/code\u003e \u003ccode\u003ejoin(', ')\u003c/code\u003e – very useful for parameter lists. This can also take an attribute name, so \u003ccode\u003ejoin(', ', 'name')\u003c/code\u003e will join the name attributes of the elements of the sequence.\u003c/li\u003e\u003c/ul\u003e\r\nMore rarely useful ones include:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#wordwrap\" rel\u003d\"nofollow\"\u003ewordwrap\u003c/a\u003e:\u003c/code\u003e \u003ccode\u003ewordwrap(80, false)\u003c/code\u003e – alternative to Python \u003ca href\u003d\"https://docs.python.org/2/library/textwrap.html\" rel\u003d\"nofollow\"\u003e\u003ccode\u003etextwrap\u003c/code\u003e\u003c/a\u003e module.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eParticularly useful filters for block control statements include:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#dictsort\" rel\u003d\"nofollow\"\u003e\u003ccode\u003edictsort\u003c/code\u003e\u003c/a\u003e\u003ccode\u003e: {% for i in d|sort %}, {% for i in d|sort(false, 'name') %}\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#length\" rel\u003d\"nofollow\"\u003e\u003ccode\u003elength\u003c/code\u003e\u003c/a\u003e\u003ccode\u003e: {% if foo|length \u0026gt; 1 %}\u003c/code\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#sort\" rel\u003d\"nofollow\"\u003e\u003ccode\u003esort:\u003c/code\u003e\u003c/a\u003e\u003ccode\u003e {% for x in l|sort %}, \u003c/code\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003e{% for x in l|sort(attribute\u003d'name') %}\u003c/span\u003e – note that given a Python set, it is clearer to convert it to a sorted list via \u003ccode\u003el \u003d sorted(s)\u003c/code\u003e in Python, but for unsorted lists, it's clearer to sort in Jinja.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Jinja-environment\" /\u003eJinja environment\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe overall setup of Jinja calls the \u003ca href\u003d\"http://jinja.pocoo.org/docs/api/#jinja2.Environment\" style\u003d\"font-size:10pt;background-color:transparent\" rel\u003d\"nofollow\"\u003e\u003ccode\u003ejinja2.Environment\u003c/code\u003e\u003c/a\u003e constructor. There are a few flags which are very useful for whitespace control, and should be used (these need to be manually specified due to backwards compatibility); these are indicated below. After initializing the environment, if you have any custom filters, you'll need to add them to \u003ca href\u003d\"http://jinja.pocoo.org/docs/api/#jinja2.Environment.filters\" rel\u003d\"nofollow\"\u003e\u003ccode\u003eenvironment.filters\u003c/code\u003e\u003c/a\u003e.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003ejinja_env \u003d jinja2.Environment(\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    loader\u003djinja2.FileSystemLoader(templates_dir),\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    keep_trailing_newline\u003dTrue,  # newline-terminate generated files\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    lstrip_blocks\u003dTrue,  # so can indent control flow tags\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    trim_blocks\u003dTrue)  # so don't need {%- -%} everywhere\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ejinja_env.filters.update({\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    'foo': foo,\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    # ...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e})\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Style\" /\u003eStyle\u003c/h2\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Python-Jinja-split\" /\u003ePython/Jinja split\u003c/h3\u003e\r\n\u003cdiv\u003eIn Jinja usage, the logic and code generation is not strictly split between the Python logic and the Jinja templates, and the boundary is sometimes a matter of taste.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo understand a Jinja template, please open \u003ci\u003eboth\u003c/i\u003e the Jinja template \u003ci\u003eand\u003c/i\u003e the Python script that computes the context and refer to both, preferably by mainly reading the Jinja, and referring to the Python when necessary to understand how variables are computed.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003eAs a rule:\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003emulti-line code should be in templates,\u003c/li\u003e\r\n\u003cli\u003ecomponents should be assembled in templates, and\u003c/li\u003e\r\n\u003cli\u003ecomplex logic should be in Python.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eSimple logic (list filtering, ternary operations, simple auxiliary variables) should be in templates, but complex logic (anything that doesn't fit in a single expression), should be in Python, and the Jinja side should just have a variable.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eAs an example of the boundary is a method call. Unless there is complex logic, this should be assembled primarily in the template:\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e{{method.namespace}}::{{method.name}}({{method.arguments | join(', ')}});\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eBy contrast, if there is complex logic, the logic should be in Python, and the template code should just contain a variable:\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:normal\"\u003e\u003ccode\u003e{{method.call_expression}};\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003eNote that semicolons and linebreaks should be in the template, not the Python code!\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003cdiv\u003eFor lists: simple iteration and filtering should be in Jinja, but list building or complex iteration should generally go in Python.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003eA good example of complex logic in the bindings generator is the expression for a Blink getter (method to call and arguments to pass), which is computed by \u003ccode\u003egetter_expression()\u003c/code\u003e in Python, and used as \u003ccode\u003e{{attribute.cpp_value}}\u003c/code\u003e in Jinja (so called because it might be \u003ccode\u003e'resultValue'\u003c/code\u003e instead, in cases where the value is stored in a local variable in the getter method).\u003c/div\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Do-not-call-Python-functions-from-Jinja-except-custom-filters-\" /\u003eDo not call Python functions from Jinja (except custom filters)\u003c/h4\u003e\u003cdiv\u003ePython functions should be called \u003ci\u003ein Python\u003c/i\u003e to generate context values; this ensures a one-directional Python → Jinja pipeline. It is possible to pass Python functions as Jinja context values, and then call them in Jinja, but this makes the template hard to read and introduces a Python ⇄ Jinja cycle, which makes it harder to understand the code. This does create distance between computation and use (e.g., if there's a variable name in the template, and you want to compute a function call using that variable): if a Jinja context value should be computed in a certain way, adding a brief comment to that effect in the template is fine.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eNote that custom filters are Python functions, but they are intended to be called from Jinja, and are idiomatic.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Python\" /\u003ePython\u003c/h3\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-One-dictionary-display-per-context-inline-expressions\" /\u003eOne dictionary display per context, inline expressions\u003c/h4\u003e\r\n\u003cdiv\u003eIdeally, the Python logic for a given context will be a single \u003ca href\u003d\"http://docs.python.org/2/reference/expressions.html#dictionary-displays\" style\u003d\"color:rgb(85,26,139)\" rel\u003d\"nofollow\"\u003edictionary display\u003c/a\u003e (like a dictionary literal, but keys and values can be expressions, not literals), with the keys being (string) literals and the values being Python expressions: the function is just \u003ccode\u003ereturn {'bar': ..., 'foo': ..., ...}\u003c/code\u003e. This means you can just look up the key in the context-generation code, and is very functional and flat (instead of building up the context in various functions, which makes lookup harder). In the bindings generator, \u003ccode\u003ev8_methods\u003c/code\u003e, \u003ccode\u003emethod_context\u003c/code\u003e and \u003ccode\u003eargument_context\u003c/code\u003e (currently \u003ccode\u003egenerate_method\u003c/code\u003e and \u003ccode\u003egenerate_argument\u003c/code\u003e) are good examples: each corresponds to a single object type (\u003ccode\u003eIdlOperation\u003c/code\u003e and \u003ccode\u003eIdlArgument\u003c/code\u003e), and generates a dict, nested corresponding to the nesting of objects.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Logic-and-local-variables-before-display\" /\u003eLogic and local variables before display\u003c/h4\u003e\r\n\u003cdiv\u003eHowever, in some cases the code needs to do additional processing, not just produce a context value. In that case the additional logic should come \u003ci\u003ebefore\u003c/i\u003e the display, and use local variables, which are then used as values in the dictionary display. For example, if there are side effects, this should come before the display: compute a local variable, test that variable and have side effects if necessary, then use the variable in the display (no local variable needed if value not needed in context, only side effects). A more complex case is when one context value is a combination of several others; in that case the individual values are computed before the display, stored in local variables, and then combined in the display.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Separate-functions-if-necessary\" /\u003eSeparate functions if necessary\u003c/h4\u003e\r\n\u003cdiv\u003eIn some cases complex calculations are better factored into a separate function, with the main dictionary updated via \u003ccode\u003edict.update()\u003c/code\u003e. If later calculations depend on earlier ones, the context computed so far can be passed in as an argument, and the dict updated in place. In the bindings generator a good example is the context for getters and setters for attributes: the logic is relative complicated, and depends on previously computed variables, so this is factored into separate functions, and the existing context dict is passed in as an argument, which is updated in place.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Early-return-if-necessary\" /\u003eEarly return if necessary\u003c/h4\u003e\r\n\u003cdiv\u003eIn rare cases, the context-generation code will have an early return after the main display, and then additional processing afterwards.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Jinja\" /\u003eJinja\u003c/h3\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Keep-it-simple\" /\u003eKeep it simple\u003c/h4\u003e\r\n\u003cdiv\u003eJinja templates are in a \u003ca href\u003d\"http://en.wikipedia.org/wiki/Domain-specific_language\" rel\u003d\"nofollow\"\u003edomain-specific language\u003c/a\u003e (DSL), which is not familiar to most developers. Thus try to keep it simple.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Spacing\" /\u003eSpacing\u003c/h4\u003e\r\n\u003cdiv\u003eWe use the following spacing:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{{foo}}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{{foo | filter}}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% for i in x|filter %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\nI.e., no spacing within \u003ccode\u003e{{}}\u003c/code\u003e, but do space around \u003ccode\u003e|\u003c/code\u003e, except in block control statements. This is the opposite of Jinja spec convention, which is \u003ccode\u003e{{ foo }}\u003c/code\u003e and \u003ccode\u003e{{ foo|filter }}\u003c/code\u003e – reasoning is that \u003ccode\u003e{{}}\u003c/code\u003e are functioning like parentheses or quotes, hence no spacing inside them; while \u003ccode\u003e|\u003c/code\u003e is functioning like a binary operator, like arithmetic operations, hence spaces around it. However, in block control statements \u003ccode\u003e|\u003c/code\u003e has higher precedence than the control flow keywords, and thus omitting spaces makes the precedence clearer.\u003c/div\u003e\r\n\u003cdiv\u003eMore pragmatically, \u003ccode\u003e{{}}\u003c/code\u003e is very widely used for variable substitution, hence want to keep it short and looking like a single unit, while usage of filters via \u003ccode\u003e|\u003c/code\u003e is logically complex, and thus should stick out visually, with the steps in the pipeline clearly separated. However, adding spaces within a block control statement makes it confusing, due to the spaces around the control flow keywords, and thus spaces around \u003ccode\u003e|\u003c/code\u003e should be omitted.\u003cbr /\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-set-if-simple-and-used-in-only-one-place\" /\u003eset if simple and used in only one place\u003c/h4\u003e\r\n\u003cdiv\u003eIt is ok to use a \u003ccode\u003eset\u003c/code\u003e statement if a value is only useful in one place, and can be derived from existing data, which avoids cluttering the context display, but if a value is used multiple places or would require additional auxiliary variables just for it, it's better to compute it in the context display.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Variables-should-be-complete-words-not-fragments\" /\u003eVariables should be complete words, not fragments\u003c/h4\u003e\r\n\u003cdiv\u003eVariables should be \u003ci\u003ecomplete words\u003c/i\u003e, not fragments, notably not affixes (prefixes and suffixes).\u003c/div\u003e\r\n\u003cdiv\u003eThis is particularly important for literal values, due to searching, but also goes for variable values.\u003c/div\u003e\r\n\u003cdiv\u003eComplete words are more legible, and can be searched for automatically.\u003c/div\u003e\r\n\u003cdiv\u003eFor example:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:normal\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set ref_ptr \u003d 'RefPtrOrNull' if nullable else 'RefPtr' %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...{{ref_ptr}}...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eCompare to the use of fragments \u003cb\u003e(don't do this!):\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-weight:normal\" /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:normal\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set or_null \u003d 'OrNull' if nullable else '' %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...RefPtr{{or_null}}... // try grepping for \"RefPtrOrNull\"!\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThis also goes if the root itself is a variable: modify the variable via \u003ccode\u003eset\u003c/code\u003e instead of creating a new affix variable.\u003c/div\u003e\r\n\u003cdiv\u003eThis keeps the variable as a unit, and makes the substitution easier to read:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set bar \u003d bar + ('Constructor' if is_constructor else '') %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e..., {{foo}}, {{bar}}, ...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nCompare to the use of fragments \u003cb\u003e(don't do this!):\u003c/b\u003e\u003cbr /\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set bar_suffix \u003d 'Constructor' if is_constructor else '' %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e..., {{foo}}, {{bar}}{{bar_suffix}}, ...\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Name-variables-after-default-value\" /\u003eName variables after default value\u003c/h4\u003e\r\n\u003cdiv\u003eA common use case is for a variable to have a default value, but sometimes have a different value, particularly an affix. This is easier to read if you name the variable after the default value, like:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e'foo': 'foo.bar' if bar else 'foo',\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eor:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e{% set foo \u003d 'foo.bar' if bar else 'foo' %}\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e...which can then be used as \u003ccode\u003e{{foo}}\u003c/code\u003e in templates, which mentally translates as \"usually \u003ccode\u003efoo\u003c/code\u003e, but sometimes something else\".\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Comment-end-of-long-blocks\" /\u003eComment end of long blocks\u003c/h4\u003e\r\n\u003cdiv\u003eIf a block is long, particularly if it is nested, please add a comment at the end to help clarify which block is ending; use the same content as the \u003ccode\u003eif\u003c/code\u003e condition or \u003ccode\u003efor\u003c/code\u003e list.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if foo %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if bar \u003d\u003d 'zork' %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}{# bar \u003d\u003d 'zork' #}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}{# foo #}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e{% for x in l %}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endfor %}{# x in l #}\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNote that if there are nested blocks, there's no need to comment the end of a short inner block, but you should comment the outer block:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e{% if foo %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if bar %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% else %}{# foo #}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if bar %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}{# foo #}\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Use-implicit-False\" /\u003eUse implicit \u003ccode\u003eFalse\u003c/code\u003e\u003c/h4\u003e\r\n\u003cdiv\u003eAs in usual Python style (\u003ca href\u003d\"http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone\u003dTrue/False_evaluations#True/False_evaluations\"\u003eTrue/False evaluations\u003c/a\u003e), you can use implicit \u003ccode\u003eFalse\u003c/code\u003e. \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eContext variables can be used as both content (filled into expressions) and control (determining control flow); a common technique is to check for the existence of a content variable as a conditional, which avoids a separate boolean variable just for control. Compare \u003c/span\u003e\u003ccode style\u003d\"background-color:transparent;font-size:10pt\"\u003e{% if foo %}...{{foo}}...{% endif %}\u003c/code\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e to \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;background-color:transparent;font-size:10pt\"\u003e{% if is_foo %}...{{foo}}...{% endif %}\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Whitespace\" /\u003eWhitespace\u003c/h4\u003e\r\n\u003cdiv\u003eWhitespace handling can be \u003ci\u003every\u003c/i\u003e fiddly, particularly around line breaks.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eFirst, make sure you've set up your Jinja environment with the whitespace control flags – \u003ccode\u003ekeep_trailing_newline, lstrip_blocks, trim_blocks\u003c/code\u003e – this will ensure that whitespace will be generally sane, and you can use blocks without needing to worry about whitespace most of the time. In old code you'll often see lots of explicit \u003ccode\u003e{%- ... -%}\u003c/code\u003e which are not necessary with these flags.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSecondly, it's easiest to define macros in a separate library, as this allows you to not worry about the whitespace caused by the macro definitions themselves, and also yields better factoring.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe default behavior these flags give is to treat lines that only contain a block (possibly indented) as not there whitespace-wise. Thus:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e    {% if foo %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    {% endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e...will only output a single line, despite the 2 lines of (indented) block statements.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNote however that expression evaluation in \u003ccode\u003e{{ ... }}\u003c/code\u003e are \u003ci\u003enot\u003c/i\u003e trimmed; this is a particular issue for macros. Thus:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003ccode\u003e{{foo()}}\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e...\u003ci\u003edoes\u003c/i\u003e include a trailing newline, even if \u003ccode\u003efoo()\u003c/code\u003e evaluates to empty (\u003ccode\u003e''\u003c/code\u003e). Thus if you would like a section of the template to be omitted entirely in some cases, it is simplest to use a block, as in template inheritance.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eManual whitespace handling can be specified with \u003ccode\u003e{%-, -%}, {{-, -}},\u003c/code\u003e to trim surrounding whitespace, and \u003ccode\u003e{%+\u003c/code\u003e to \u003ci\u003enot\u003c/i\u003e strip a leading indent. Trimming can be very confusing, so it's generally best to only use it when there's a literal boundary (literal text that will be stripped until), not when next to another block or expression; this also means to strip at the innermost level.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eCases where manual whitespace handling commonly occur:\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eIn-line macros: end with \u003ccode\u003e{%- endmacro %}\u003c/code\u003e, or strip inside conditional block as \u003ccode\u003e{%- else %}...{%- endif %}\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eFor a macro that's expected to be used inline \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e–\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e like \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003ea, {{f()}}, b\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e – you need to trim or omit the trailing newlines in the macro definition, otherwise it will include a newline when expanded. This can be done via \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003e{%-\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e as follows. Note that you only need to trim \u003c/span\u003e\u003ci style\u003d\"font-size:10pt;background-color:transparent\"\u003eimmediately after the newline,\u003c/i\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e not repeatedly.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e{% macro f() %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- endmacro %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% macro g() %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endmacro %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eThese are equivalent to omitting the line breaks, but allow more legible block positioning; omitting linebreaks yields the less legible:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e{% macro foo() %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003ccode\u003e{% endmacro %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% macro g() %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...{% else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...{% endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endmacro %}\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eBlock at start of line, keep indent: use \u003ccode\u003e{%+\u003c/code\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eIf you need to include an optional start of an indented line, use \u003ccode\u003e{%+\u003c/code\u003e to keep the initial indent:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    {%+ if foo %}... {% endif %}...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eSplit single line across multiple lines: avoid, use \u003ccode\u003e{%- ... -%}\u003c/code\u003e (\u003ccode\u003e-\u003c/code\u003e next to excess newline)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eIt's best to avoid complex conditional logic within a line. It's often simpler to set an auxiliary variable before the line and then just include that. Similarly, given multiple conditionals, such as an arguments list, it's often easier to have a list variable for the arguments and then build the arguments with \u003ccode\u003e{{args | join(', ')}}\u003c/code\u003e as in:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set args \u003d ['foo'] if foo else [] %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set args \u003d args + ['bar'] %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% set args \u003d args + (['zork'] if zork else []) %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ef({{args | join(', ')}});\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\nHowever, if you wish to include the logic inline and split across multiple lines for legibility, the rule is: \"use \u003ccode\u003e-\u003c/code\u003e next to the excess newline\", making sure you're ultimately surrounded by literal text. For one-line conditionals, you just need \u003ccode\u003e{%-\u003c/code\u003e and \u003ccode\u003e%-}\u003c/code\u003e for the outermost tags. A common use is argument lists; note the spacing and comma usage.\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003ef(\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    {%- if foo %}foo, {% endif -%}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    bar\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    {%- if zork %}, zork{% endif -%}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e);\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nThe actual whitespace rules mean that you can omit some of these trim instructions (if there are consecutive blocks, for instance), but it is simpler and more robust to include them (this lets blocks be added and removed without worrying about whitespace, for instance). For extra-long lines where you want to split the condition and contents across separate lines, you should use \u003ccode\u003e{%- ... -%}\u003c/code\u003e for each block, to ensure trimming:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003ef(\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- if very_long_condition_indeed -%}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003every_long_argument_name_with_bells_and_whistles\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- else -%}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eother_very_long_argument_name_with_bells_whistles_and_ribbons_too\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- endif -%}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e);\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eLong block at start of line, keep indent and split: use \u003ccode\u003e{%+ ... -%}\u003c/code\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\nThe above two can be combined if you have a long block at the start of a line. This is the most complex case you are likely to encounter:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e    {%+ if foo %}[VeryLongExtendedAttributeName, AndThenAnotherOne] {% endif -%}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    attribute DOMString name;\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Treat-multi-line-macros-as-blocks-indent-trailing-semicolon-in-macro-\" /\u003eTreat multi-line macros as blocks (indent, trailing semicolon \u003ccode\u003e;\u003c/code\u003e in macro)\u003c/h4\u003e\r\n\u003cdiv\u003eIf a macro expands to multiple lines of output in an indented block (common in generating C++ code), in order for the output to be properly indented:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eDo not indent the body of the macro.\u003c/li\u003e\r\n\u003cli\u003eUse the \u003ccode\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/templates/#indent\" rel\u003d\"nofollow\"\u003eindent\u003c/a\u003e\u003c/code\u003e filter at the call site.\u003c/li\u003e\u003c/ul\u003e\r\nThe indent defaults to adding an indent to all but the first line; use \u003ccode\u003eindent(8)\u003c/code\u003e (or \u003ccode\u003eindent(12)\u003c/code\u003e etc.) if you need to indent further, and \u003ccode\u003eindentfirst\u003dTrue\u003c/code\u003e if you need to indent the first line as well, as \u003ccode\u003eindent(8, True)\u003c/code\u003e or \u003ccode\u003eindent(indentfirst\u003dTrue)\u003c/code\u003e.\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003eF\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eor more complex logic, like not indenting preprocessor directives in C++, you'll need to write a \u003ca href\u003d\"http://jinja.pocoo.org/docs/api/#writing-filters\" rel\u003d\"nofollow\"\u003ecustom filter\u003c/a\u003e.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor example, definition:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e{% macro f(x) %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if x %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ea(x);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eb(x);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ea(y);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eb(y);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endmacro %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eUse:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    b();\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    {{f() | indent}}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    c();\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Treat-one-line-macros-as-in-line-no-indent---to-strip-trailing-linebreak-semicolon-at-call-site-\" /\u003eTreat one-line macros as in-line (no \u003ccode\u003eindent\u003c/code\u003e, \u003ccode\u003e{%-\u003c/code\u003e to strip trailing linebreak, semicolon \u003ccode\u003e;\u003c/code\u003e at call site)\u003c/h4\u003e\r\n\u003cdiv\u003eSome macros generate exactly one line of content. These should be treated as in-line macros: they do not need an indent, you should strip the trailing linebreak in the macro, and any trailing context (notably a semicolon) should be at the call site. This simplifies both the macro and the call, improves consistency, and emphasizes that it is a one-line macro.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eFor example, definition:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e{% macro f(x) %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if x %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ea(x)\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ea(y)\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{%- endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endmacro %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nUse:\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    b();\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    {{f()}};\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    c();\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    ...\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-C-code-generation\" /\u003eC++ code generation\u003c/h4\u003e\r\n\u003cdiv\u003eTemplated code generation (esp. C++ code) is particularly complicated to read, since it requires following both the flow of the template and of the generated code.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Don-t-mix-Jinja-templates-and-C-templates\" /\u003eDon't mix Jinja templates and C++ templates\u003c/h4\u003e\r\n\u003cdiv\u003eJinja templates for generating C++ code, and C++ templates (in the usual sense) have the same effect: they are transformed into C++ code, which can then be compiled. These thus fill similar roles, and one can in principle use either for some purposes. I\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ef a C++ template is only being used within Jinja-generated code, it is clearer to replace it with a Jinja template, so you don't need to keep track of 2 template systems at once.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003eIt is fine to use existing C++ templates that are used outside of the Jinja-generated code.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Group-related-code-minimize-code-within-clauses\" /\u003eGroup related code, minimize code within clauses\u003c/h4\u003e\r\n\u003cdiv\u003eAs much as possible, group related code together, particularly by having variable definitions close to use, especially immediately before; and minimize code within template clauses, particularly by having more generic code and using auxiliary variables.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eFor example:\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{# Bad #}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eT x \u003d ...;\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e...\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% if c %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ef(x, g(...));\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% else %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eT y \u003d h(...);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ef(x, y);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{% endif %}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e{# Good #}\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003eT x \u003d ...;\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e{% if c %}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eT y \u003d g(...);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e{% else %}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eT y \u003d h(...);\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e{% endif %}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ef(x, y);\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Tips\" /\u003eTips\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Syntax-highlighting\" /\u003eSyntax highlighting\u003c/h3\u003e\r\n\u003cdiv\u003eSyntax highlighting for Jinja is tricky, because ideally one wants highlighting for both languages: the target language (e.g., C++, HTML) and Jinja. Indeed, ideally one would have separate highlight colors for the target language and for Jinja (e.g., bold, inverse, or different background). This can be done, with some care.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eFor simple editing, it's fine to just use the highlighting of the target language (this is a key reason to use the extensions of the underlying file type for templates) and deal with Jinja code not being highlighted or appearing broken, but if you edit templates frequently, proper syntax highlighting is very helpful.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-vim\" /\u003evim\u003c/h4\u003e\r\n\u003cdiv\u003eIn Vim, one can achieve nested \u003ca href\u003d\"http://vimdoc.sourceforge.net/htmldoc/syntax.html\" rel\u003d\"nofollow\"\u003esyntax highlighting\u003c/a\u003e of Jinja via the following 4 steps:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eDownload \u003ca href\u003d\"http://www.vim.org/scripts/download_script.php?src_id\u003d8666\" rel\u003d\"nofollow\"\u003ejinja.syntax\u003c/a\u003e file, place in \u003ccode\u003e~/.vim/syntax\u003c/code\u003e\u003cbr /\u003e\r\n(from \u003c/span\u003e\u003ca href\u003d\"http://www.vim.org/scripts/script.php?script_id\u003d1856\" rel\u003d\"nofollow\"\u003eJinja : adds jinja highlighting support to vim\u003c/a\u003e, link is to v1.1; you might want to make one minor update, but otherwise do not need to edit this file)\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eAdd nested highlighting function to \u003ccode\u003e~/.vimrc\u003c/code\u003e\u003cbr /\u003e\r\n(per below; \u003c/span\u003efollows “\u003ca href\u003d\"http://vim.wikia.com/wiki/Different_syntax_highlighting_within_regions_of_a_file\" rel\u003d\"nofollow\"\u003eDifferent syntax highlighting within regions of a file\u003c/a\u003e”, with some modifications)\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eAdd auto commands to call this function to \u003ccode\u003e~/.vimrc\u003c/code\u003e\u003cbr /\u003e\r\n(depends on filename convention; sample below)\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ci\u003e(optional)\u003c/i\u003e Add separate Jinja-specific highlighting groups.\u003c/span\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" Per:\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" Different syntax highlighting within regions of a file\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" http://vim.wikia.com/wiki/Different_syntax_highlighting_within_regions_of_a_file\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" Important changes:\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" * Add keepend, otherwise nested C++/Jinja doesn't work!\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" * Add containedin\u003dALL, so also highlighted in C comments and strings.\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" * Remove the textSnipHl section (since want to include the delimiters\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\"   for Jinja).\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\"\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" ...and using syntax from:\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" http://www.vim.org/scripts/script.php?script_id\u003d1856\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003efunction! TextEnableCodeSnip(filetype,start,end) abort\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  let ft\u003dtoupper(a:filetype)\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  let group\u003d'textGroup'.ft\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  if exists('b:current_syntax')\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    let s:current_syntax\u003db:current_syntax\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    \" Remove current syntax definition, as some syntax files (e.g. cpp.vim)\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    \" do nothing if b:current_syntax is defined.\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    unlet b:current_syntax\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  endif\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim'\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  try\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    execute 'syntax include @'.group.' after/syntax/'.a:filetype.'.vim'\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  catch\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  endtry\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  if exists('s:current_syntax')\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    let b:current_syntax\u003ds:current_syntax\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  else\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e    unlet b:current_syntax\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  endif\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  execute 'syntax region textSnip'.ft.'\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  \\ start\u003d\"'.a:start.'\" end\u003d\"'.a:end.'\"\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  \\ keepend\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  \\ containedin\u003dALL\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e  \\ contains\u003d@'.group\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eendfunction\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003eTo automatically highlight Jinja files, add auto commands to turn on the nested highlighting. The following assumes that files in a directory named \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003etemplates\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e are Jinja templates:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" Jinja template highlighting\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" Default delimiters are {{ }}, {% %}, and {# #}, per:\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e\" http://jinja.pocoo.org/docs/templates/\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eau BufNewFile,BufRead */templates/* call TextEnableCodeSnip('jinja', '{{', '}}')\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eau BufNewFile,BufRead */templates/* call TextEnableCodeSnip('jinja', '{%', '%}')\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eau BufNewFile,BufRead */templates/* call TextEnableCodeSnip('jinja', '{#', '#}')\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"http://jinja.pocoo.org/docs/changelog/#version-2-7\" rel\u003d\"nofollow\"\u003eJinja 2.7\u003c/a\u003e slightly changed the syntax, adding \u003ccode\u003e{%+ ... %}\u003c/code\u003e, so the syntax file needs a slight change (add \u003ccode\u003e+\\?\u003c/code\u003e two places, following \u003ccode\u003e-\\?\u003c/code\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e– beware of vim's idiosyncratic regex syntax\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e). The following patch applies this:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003e--- 1.1/jinja.vim\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e+++ 1.2/jinja.vim\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e@@ -58 +58 @@\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e-syn region jinjaTagBlock matchgroup\u003djinjaTagDelim start\u003d/{%-\\?/ end\u003d/-\\?%}/ skipwhite containedin\u003dALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e+syn region jinjaTagBlock matchgroup\u003djinjaTagDelim start\u003d/{%-\\?+\\?/ end\u003d/-\\?%}/ skipwhite containedin\u003dALLBUT,jinjaTagBlock,jinjaVarBlock,jinjaRaw,jinjaString,jinjaNested,jinjaComment\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e@@ -71 +71 @@\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e-syn match jinjaStatement containedin\u003djinjaTagBlock contained skipwhite /\\({%-\\?\\s*\\)\\@\u0026lt;\u003d\\\u0026lt;[a-zA-Z_][a-zA-Z0-9_]*\\\u0026gt;\\(\\s*[,\u003d]\\)\\@!/\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e+syn match jinjaStatement containedin\u003djinjaTagBlock contained skipwhite /\\({%-\\?+\\?\\s*\\)\\@\u0026lt;\u003d\\\u0026lt;[a-zA-Z_][a-zA-Z0-9_]*\\\u0026gt;\\(\\s*[,\u003d]\\)\\@!/\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eYou can apply this via \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003ecd ~/.vim/syntax \u0026amp;\u0026amp; patch -p1\u003c/code\u003e by just copy-pasting (hit \u003ccode\u003e^D^D\u003c/code\u003e to terminate), or use a temporary file as in:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003ecd ~/.vim/syntax \u0026amp;\u0026amp; patch -p1 \u0026lt; /tmp/jinja.vim.1_1-1_2.diff\u003c/code\u003e\u003c/div\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eLastly, if you wish to have separate highlighting for Jinja (e.g., have C++ comments and Jinja comments highlighted differently), add \u003ca href\u003d\"http://vimdoc.sourceforge.net/htmldoc/syntax.html#:highlight\" rel\u003d\"nofollow\"\u003e\u003ccode\u003ehighlight\u003c/code\u003e\u003c/a\u003e commands for Jinja-specific syntax \u003ca href\u003d\"http://vimdoc.sourceforge.net/htmldoc/syntax.html#group-name\" style\u003d\"background-color:transparent;font-size:10pt\" rel\u003d\"nofollow\"\u003egroups\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e (listed in jinja.vim, particularly the last block), such as \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003ejinjaComment\u003c/code\u003e. Note that these must be specified manually (not just \"copy existing group and change one trait\"), since \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eVim syntax highlighting does not support\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e such inheritance.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Emacs\" /\u003eEmacs\u003c/h4\u003e\r\n\u003cdiv\u003e\u003ca href\u003d\"https://github.com/paradoxxxzero/jinja2-mode\" rel\u003d\"nofollow\"\u003ejinja2-mode\u003c/a\u003e is a major mode for Jinja; \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"http://web-mode.org/\" rel\u003d\"nofollow\"\u003eweb-mode\u003c/a\u003e may also work.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eSee \u003ca href\u003d\"http://www.emacswiki.org/emacs/MultipleModes\" rel\u003d\"nofollow\"\u003eMultiple Modes\u003c/a\u003e for libraries providing multiple major modes in a single buffer.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003eFIXME: do these work, say for C++ code?\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Performance\" /\u003ePerformance\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ehttp://jinja.pocoo.org/docs/api/#bytecode-cache\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003ehttps://groups.google.com/forum/#!topic/pocoo-libs/dIsNICT4j2Q\u003c/div\u003e\r\n\u003cdiv\u003ehttps://gist.github.com/voscausa/9055838\u003c/div\u003e\r\n\u003cdiv\u003ehttp://jinja.pocoo.org/docs/api/#jinja2.Environment.compile_templates\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-External-links\" /\u003eExternal links\u003c/h2\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/jinja"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7065492440810770218"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7065492440810770218"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7065492440810770218"}],"author":[{"name":{"$t":"Nils Barth"},"email":{"$t":"nbarth@chromium.org"}}],"sites$pageName":{"$t":"jinja"},"sites$revision":{"$t":"33"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5145004460919906794"},"published":{"$t":"2014-05-23T05:19:54.063Z"},"updated":{"$t":"2014-09-15T18:30:02.668Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-23T05:19:54.063Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image01.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5145004460919906794"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8110757228964464770"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/overview-of-moblab/image01.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5145004460919906794"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5145004460919906794"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5145004460919906794"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5145004460919906794"}],"author":[{}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6799517166647332577"},"published":{"$t":"2014-05-23T05:23:41.091Z"},"updated":{"$t":"2014-09-15T18:30:02.667Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-23T05:23:41.091Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image00.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6799517166647332577"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8110757228964464770"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/overview-of-moblab/image00.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6799517166647332577"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6799517166647332577"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6799517166647332577"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6799517166647332577"}],"author":[{}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7257777504967824123"},"published":{"$t":"2013-01-09T07:07:11.665Z"},"updated":{"$t":"2014-09-14T20:31:54.606Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-14T20:31:52.848Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Creating V8 profiling timeline plots"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFor visualization, timeline graphs can be plotted to show where V8 is spending time. This can be used to find bottlenecks and spot things that are unexpected (for example, too much time spent in unoptimized code). Data for the plot are gathered by both sampling and instrumentation. Since the latter distorts the performance, the plot script attempts to undistort the logged timestamps.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/Screen%20Shot%202014-09-14%20at%201.27.21%20PM.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1410726511821/developers/creating-v8-profiling-timeline-plots/Screen%20Shot%202014-09-14%20at%201.27.21%20PM.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv style\u003d\"display:block;text-align:left\" /\u003e\u003cbr /\u003e\u003ch2 style\u003d\"color:rgb(85,85,85);font-family:sans-serif\"\u003e\u003ca name\u003d\"Profiling_in_Chrome\" /\u003eProfiling in Chrome\u003c/h2\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Desktop-Chrome\" /\u003eDesktop Chrome\u003c/h3\u003e\u003c/div\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003eClose all Chrome instances (both Canary and Stable). \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003eTo profile a web site in chrome, pass the same flags to V8 using \u003c/span\u003e\u003ccode\u003e--js-flags\u003c/code\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e and with \u003c/span\u003e\u003ccode\u003e--no-sandbox\u003c/code\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e to enable writing into \u003c/span\u003e\u003ccode\u003ev8.log\u003c/code\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e. \u003c/span\u003e\u003cdiv\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFor example:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,96,0);background-color:rgb(224,234,244);border:1px solid rgb(169,206,241);padding-left:1em;padding-top:0.5em;padding-bottom:0.5em;overflow:auto\"\u003e$ ./chrome --no-sandbox --js-flags\u003d\"--prof --log-timer-events\" mail.google.com \u0026amp; sleep 10; kill $!\r\n\u003c/pre\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eGiven that Gmail is already logged into, this profiles the first 10 seconds after starting Chrome and loading Gmail, before Chrome is killed.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eThis will create a v8.log file next to the Chrome binary folder.\u003c/p\u003e\u003cp\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003eIf the plotting script fails stating that the logfile is inconsistent, retry while adding \u003c/font\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e--logfile\u003dv8-%p.log \u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eto the \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;background-color:transparent;font-size:10pt\"\u003e--js-flags\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003e, which will create a separate file for each process suffixed with the process' pid.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Chrome-on-Android\" /\u003eChrome on Android\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003eSince Android has additional security sandboxing, the renderer process will not be able to write to a file in the application's working directory (even when  \u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;background-color:transparent;font-size:10pt\"\u003e--no-sandbox \u003c/span\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eis enabled).  You must therefore create a directory which can be written by any user and instruct V8 to log it's output there.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eFor example: \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cpre style\u003d\"background-color:rgb(224,234,244);border:1px solid rgb(169,206,241);padding-left:1em;padding-top:0.5em;padding-bottom:0.5em;overflow:auto\"\u003e\u003cfont color\u003d\"#006000\"\u003e$ adb shell mkdir /data/local/tmp/v8-logs/\r\n$ adb shell chmod 777 /data/local/tmp/v8-logs/\r\n\r\n[choose adb_content_shell_command_line or adb_chromium_testshell_command_line below depending upon your target]\r\n$ ./build/android/adb_content_shell_command_line \u003c/font\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#006000\"\u003e--no-sandbox --js-flags\u003d\\\"\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#006000\"\u003e--prof --log-timer-events \u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#006000\"\u003e--logfile\u003d/data/local/tmp/v8-logs/v8.log\\\"\u003c/font\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Now-after-restarting-the-content-shell-chromium-test-shell-the-logs-will-be-available-in-data-local-tmp-v8-logs-v8.log-and-can-be-retrieved-using-adb-pull.\" /\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eNow, after restarting the content shell / chromium test shell, the logs will be available in /data/local/tmp/v8-logs/v8.log and can be retrieved using \u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:13px;font-weight:normal\"\u003eadb pull\u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-family:Times;font-size:medium;background-color:transparent\"\u003e.\u003cbr /\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Profiling-in-d8\" /\u003e\u003cspan style\u003d\"color:rgb(85,85,85);font-family:sans-serif;background-color:transparent\"\u003e\u003cfont size\u003d\"4\"\u003eProfiling in d8\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003ch2 style\u003d\"color:rgb(85,85,85);font-family:sans-serif\"\u003e\u003ca name\u003d\"TOC-To-profile-a-script-in-d8-run-d8-with-the-appropriate-flags--prof-enables-tick-based-profiling--log-internal-timer-events-enables-timing-the-runtime-of-V8-s-internal-components-such-as-the-GC-parser-compiler-etc.--log-timer-events-implies---log-internal-ti\" /\u003e\u003cspan style\u003d\"color:rgb(0,0,0);font-weight:normal;font-family:Times;font-size:medium\"\u003eTo profile a script in d8, run d8 with the appropriate flags\u003c/span\u003e\u003cul style\u003d\"color:rgb(0,0,0);font-weight:normal;font-family:Times;font-size:medium\"\u003e\u003cli\u003e\u003ccode\u003e--prof\u003c/code\u003e enables tick based profiling\u003c/li\u003e\u003cli\u003e\u003ccode\u003e--log-internal-timer-events\u003c/code\u003e enables timing the runtime of V8's internal components such as the GC, parser, compiler, etc.\u003c/li\u003e\u003cli\u003e\u003ccode\u003e--log-timer-events\u003c/code\u003e implies \u003ccode\u003e--log-internal-timer-events\u003c/code\u003e, but also times external callbacks.\u003c/li\u003e\u003c/ul\u003e\u003cp style\u003d\"color:rgb(0,0,0);font-weight:normal;font-family:Times;font-size:medium\"\u003eFor example\u003c/p\u003e\u003cpre style\u003d\"font-size:13px;font-weight:normal;color:rgb(0,96,0);background-color:rgb(224,234,244);border:1px solid rgb(169,206,241);padding-left:1em;padding-top:0.5em;padding-bottom:0.5em;overflow:auto\"\u003e$ out/native/d8 --prof --log-timer-events imaging-darkroom.js\r\n\u003c/pre\u003e\u003cp style\u003d\"color:rgb(0,0,0);font-weight:normal;font-family:Times;font-size:medium\"\u003eThe log entries will be written into \u003ccode\u003ev8.log\u003c/code\u003e\u003c/p\u003e\u003cp style\u003d\"color:rgb(0,0,0);font-weight:normal;font-family:Times;font-size:medium\"\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/p\u003e\u003c/h2\u003e\u003ch2 style\u003d\"color:rgb(85,85,85);font-family:sans-serif\"\u003e\u003ca name\u003d\"Plotting\" /\u003ePlotting\u003c/h2\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003eFind the sure you have the \u003c/span\u003e\u003ccode\u003eisolate-***.log \u003c/code\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eor\u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003e v8.log\u003c/code\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003e file created during profiling. It was created in the folder you launched that command from. \u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003eOpen \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003e\u003ca href\u003d\"https://v8.googlecode.com/svn/branches/bleeding_edge/tools/profviz/profviz.html\"\u003ehttps://v8.googlecode.com/svn/branches/bleeding_edge/tools/profviz/profviz.html\u003c/a\u003e \u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eIn the file picker dialog, select the log file you want to view. \u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eHit start and wait a few seconds for the plot to generate\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium;background-color:transparent\"\u003eYou can modify the range selection and hit Start again to replot.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2 style\u003d\"color:rgb(85,85,85);font-family:sans-serif\"\u003e\u003ca name\u003d\"Interpretation_of_the_plot_A_cas\" /\u003eInterpretation of the plot. A case study.\u003c/h2\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eLet's profile \u003ca href\u003d\"http://www.google.com/url?sa\u003dD\u0026amp;q\u003dhttp%3A%2F%2Foctane-benchmark.googlecode.com\"\u003eOctane's\u003c/a\u003e pdfjs benchmark. Due to the nature of the benchmark, having many accesses to typed arrays, we expect a considerable amount of time being spent in external callbacks (which implement typed arrays).\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFigure 1: Using only \u003ccode\u003e--prof\u003c/code\u003e, the resulting plot only contains the sampling based data. Note that the granularity isn't really enough to get a good picture of all this. The colors of the top-most javascript stack frames show that we are running more and more optimized code.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/0-prof-only.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1357715497931/developers/creating-v8-profiling-timeline-plots/0-prof-only.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cb\u003eGCScavenger\u003c/b\u003e: young space GC\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cb\u003eGCCompactor\u003c/b\u003e: old space full GC\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cb\u003eExecute\u003c/b\u003e: time spent executing JS code (as opposed to GC, waiting on native APIs to return, etc.)\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cb\u003eCode kind:\u003c/b\u003e color indicates optimized (green) vs. unoptimized (red, “full code”)\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFigure 2: Adding the option \u003ccode\u003e--log-internal-timer-events\u003c/code\u003e we still get roughly the same benchmark score, so we can be sure that the resulting plot has not been distorted by a lot by instrumentation. We now have a clearer breakdown of the time spent on this benchmark. We can see that parsing the source takes a sizeable chunk of time, which also leads to an execution pause. We also see that at the beginning, a lot of recompiling (optimizing) is going on. However, we do not see the external callbacks that we are expecting. Without additional instrumentation, those are incorrectly attributed to V8's execution time.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/1-plot-internal.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Figure 2\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1357715519997/developers/creating-v8-profiling-timeline-plots/1-plot-internal.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFigure 3: Using \u003ccode\u003e--time-timer-events\u003c/code\u003e instead and plotting with \u003ccode\u003eDISTORTION\u003d0\u003c/code\u003e, we can see that we are indeed spending a lot of time in callbacks. However, the benchmark score is only a fraction of what it should have been. Comparing this plot with previous ones, we can see that it is severely distorted by instrumentation. Heterogeneous sampling ticks, observable by unevenly distributed white gaps, are yet another indication.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/2-distorted.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Figure 3\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1357715649905/developers/creating-v8-profiling-timeline-plots/2-distorted.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFigure 4: Having the distortion parameter automatically calibrated (plot range is manually set for easier comparison), we can see that due to the instrumentation overhead, the benchmark run with instrumentation only executed a fraction of what would have been without instrumentation. The background to this is that Octane benchmarks are repeated until a minimum length of run time has been reached. The un-instrumented run manages to complete more iterations of the benchmark than the instrumented run, in the same length of run time.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eNow that the plot has been undistorted, it almost completely agrees with previous plots in figures 1 and 2.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/3-undistorted.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Figure 4\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1357715702096/developers/creating-v8-profiling-timeline-plots/3-undistorted.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFigure 5: Zooming into the interesting part of the undistorted plot.\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/4-autoscale.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg alt\u003d\"Figure 5\" border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1357715708721/developers/creating-v8-profiling-timeline-plots/4-autoscale.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Other-resources\" /\u003eOther resources\u003c/h2\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,helvetica,sans-serif\"\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://code.google.com/p/v8/wiki/V8Profiler\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003ehttp://code.google.com/p/v8/wiki/V8Profiler\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://developers.google.com/v8/profiler_example\" style\u003d\"color:rgb(17,85,204)\" target\u003d\"_blank\"\u003ehttps://developers.google.com/v8/profiler_example\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7257777504967824123"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7257777504967824123"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7257777504967824123"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$pageName":{"$t":"creating-v8-profiling-timeline-plots"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1113220135149405850"},"published":{"$t":"2014-09-14T20:28:31.793Z"},"updated":{"$t":"2014-09-14T20:28:31.821Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-14T20:28:31.793Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2014-09-14 at 1.27.21 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1113220135149405850"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7257777504967824123"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/Screen%20Shot%202014-09-14%20at%201.27.21%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1113220135149405850"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1113220135149405850"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1113220135149405850"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1113220135149405850"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4882797491595921344"},"published":{"$t":"2014-09-14T20:20:59.439Z"},"updated":{"$t":"2014-09-14T20:22:30.042Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-14T20:22:30.030Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2014-09-14 at 1.20.48 PM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4882797491595921344"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7257777504967824123"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/creating-v8-profiling-timeline-plots/Screen%20Shot%202014-09-14%20at%201.20.48%20PM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4882797491595921344"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4882797491595921344"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4882797491595921344"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4882797491595921344"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2679669516128445225"},"published":{"$t":"2014-09-14T19:21:42.783Z"},"updated":{"$t":"2014-09-14T19:21:42.809Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-14T19:21:42.783Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromium_os_yoshi_flex.tar.gz"},"summary":{},"content":{"type":"application/x-gzip","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2679669516128445225"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1511019955850917035"},{"rel":"alternate","type":"application/x-gzip","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/servo/chromium_os_yoshi_flex.tar.gz"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2679669516128445225"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2679669516128445225"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2679669516128445225"},{"rel":"edit-media","type":"application/x-gzip","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2679669516128445225"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9122431417393687172"},"published":{"$t":"2014-09-12T20:42:29.497Z"},"updated":{"$t":"2014-09-12T20:42:29.536Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-12T20:42:29.497Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"servo_v2_bot.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/9122431417393687172"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1511019955850917035"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/servo/servo_v2_bot.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9122431417393687172"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9122431417393687172"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9122431417393687172"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/9122431417393687172"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2422547830025692048"},"published":{"$t":"2014-09-12T20:42:10.407Z"},"updated":{"$t":"2014-09-12T20:42:10.438Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-12T20:42:10.407Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"servo_v2_top.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2422547830025692048"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1511019955850917035"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/servo/servo_v2_top.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2422547830025692048"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2422547830025692048"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2422547830025692048"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2422547830025692048"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4701873728563682446"},"published":{"$t":"2014-09-12T20:41:48.570Z"},"updated":{"$t":"2014-09-12T20:41:48.592Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-12T20:41:48.570Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"810-10010-03_20120227_servo_SCH_0.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4701873728563682446"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1511019955850917035"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/servo/810-10010-03_20120227_servo_SCH_0.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4701873728563682446"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4701873728563682446"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4701873728563682446"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4701873728563682446"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8913140947825639585"},"published":{"$t":"2014-09-12T20:41:29.085Z"},"updated":{"$t":"2014-09-12T20:41:29.109Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-12T20:41:29.085Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"LICENSE"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8913140947825639585"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1511019955850917035"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/servo/LICENSE"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8913140947825639585"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8913140947825639585"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8913140947825639585"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8913140947825639585"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3945530384916684779"},"published":{"$t":"2014-09-12T20:40:26.804Z"},"updated":{"$t":"2014-09-12T20:40:26.854Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-12T20:40:26.804Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromium_os_servo_v2.tar.gz"},"summary":{},"content":{"type":"application/x-gzip","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3945530384916684779"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1511019955850917035"},{"rel":"alternate","type":"application/x-gzip","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/servo/chromium_os_servo_v2.tar.gz"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3945530384916684779"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3945530384916684779"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3945530384916684779"},{"rel":"edit-media","type":"application/x-gzip","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3945530384916684779"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Wil7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"},"published":{"$t":"2014-09-10T21:48:48.506Z"},"updated":{"$t":"2014-09-11T21:45:57.969Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-11T21:23:57.886Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Anatomy of Jank"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003eauthor: wiltzius@\u003c/p\u003e\u003cbr /\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Intro\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIntro\u003c/span\u003e\u003c/h2\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eRendering performance is a huge topic of great interest to the Chrome project and web developers. As the web platform is essentially an application development framework, ensuring it has the capability to handle input and put new pixels on the screen at a speed that keeps up with the display’s refresh rate is critical.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e“Performance” is an oft-cited problem area for web developers. We spend a lot of time investigating and (hopefully) improving performance of the platform, often guided by specific bad examples. This is the pursuit and elimination of jank. \u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBut what does jank mean? What are people complaining about when they say a web page “feels slow”? This document attempts to categorize the various symptoms that all get put under the “jank” category, for the purposes of accurate identification and precise discussion.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;line-height:17.25px;white-space:pre-wrap\"\u003eTo understand the descriptions of potential causes of jank, it's important to understand roughly how rendering works. See \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/the-rendering-critical-path\"\u003eThe Rendering Critical Path\u003c/a\u003e for a primer; these two documents should be read together.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;line-height:17.25px;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;line-height:17.25px;white-space:pre-wrap\"\u003eFinally, a note on the videos of examples -- video playback performance can tragically mask subtle performance problems as it frequently isn't rendered at 60Hz. The examples here should be obvious enough that the problem is still visible, but the originals of these videos are attached to the page, which you can download for slightly more accurate recordings.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Symptom-Taxonomy\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSymptom Taxonomy\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Intro\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntro\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Symptom-Taxonomy\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eSymptom Taxonomy\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Incomplete-content\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eIncomplete content\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Checkerboarding\"\u003e\u003cstrong\u003e2.1.1 \u003c/strong\u003eCheckerboarding\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Checkerboarding-special-case:-low-resolution-tiles\"\u003e\u003cstrong\u003e2.1.1.1 \u003c/strong\u003eCheckerboarding special case: low resolution tiles\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Checkerboarding-common-cause:-URL-bar-jank\"\u003e\u003cstrong\u003e2.1.1.2 \u003c/strong\u003eCheckerboarding common cause: URL bar jank\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Partial-content-during-network-load\"\u003e\u003cstrong\u003e2.1.2 \u003c/strong\u003ePartial content during network load\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Framerate\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eFramerate\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Low-sustained-framerate-during-any-kind-of-animation-janky-animations-\"\u003e\u003cstrong\u003e2.2.1 \u003c/strong\u003eLow sustained framerate during any kind of animation (“janky animations”)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Delayed-beginning-to-any-animation\"\u003e\u003cstrong\u003e2.2.2 \u003c/strong\u003eDelayed beginning to any animation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Low-framerate-during-to-swipe-input-throughput-\"\u003e\u003cstrong\u003e2.2.3 \u003c/strong\u003eLow framerate during to swipe input (throughput)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Isolated-long-pauses-jank-during-JS-driven-animations-incl-touch-\"\u003e\u003cstrong\u003e2.2.4 \u003c/strong\u003eIsolated long pauses (“jank”) during JS-driven animations (incl touch)\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Latency\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eLatency\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-High-scrolling-latency-or-delays-beginning-scrolling-when-the-document-has-touch-event-handlers\"\u003e\u003cstrong\u003e2.3.1 \u003c/strong\u003eHigh scrolling latency or delays beginning scrolling when the document has touch event handlers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Scroll-linked-effects-out-of-sync\"\u003e\u003cstrong\u003e2.3.2 \u003c/strong\u003eScroll-linked effects out of sync\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Incomplete-content\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIncomplete content\u003c/span\u003e\u003c/h3\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Checkerboarding\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCheckerboarding\u003c/span\u003e\u003c/h5\u003e\u003cbr /\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed\" style\u003d\"width:853px;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eYouTube Video\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-youtube\"\u003e\u003ciframe title\u003d\"YouTube video player\" class\u003d\"youtube-player\" type\u003d\"text/html\" src\u003d\"https://www.youtube.com/embed/_JQNvjBXV7k?rel\u003d0\u0026amp;wmode\u003dopaque\" frameborder\u003d\"0\" allowFullScreen\u003d\"true\" width\u003d\"853\" height\u003d\"480\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e Parts of the page not showing up, particularly during a fast scroll or animation, and instead patches of either a gray checkerboard pattern or the background of the page showing through.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSome background, for the curious. The checkerboarding problem is a very fundamental one for a document viewer: do you preserve responsiveness to user input or do you only show fully correct content? Chrome has developed a lot of (expensive) machinery to combat this problem, preferencing responsiveness. Checkerboarding occurs mainly during fast scrolling, when the page cannot be rasterized quickly enough to put up a new viewport’s worth of content every frame. When this happens Chrome will continue to scroll in an attempt to preserve the physical metaphor of page under the user’s finger... but in place of the missing content there will just be a blank space. On desktop platforms Chrome will draw a greyish checkerboard pattern; on Android (where this is more common) it draws the background color of the page.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eTo try to avoid having to checkerboard Chrome will pre-rasterize content around the viewport and keep it as bitmaps in memory. This policy trades CPU and memory resource consumption for a greater likelihood that the page content will be ready if/when the user starts scrolling. It’s essentially a giant buffer to guard against how slow software rasterization can be.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis approach has several limitations. For one, it’s a bit of a resource hog. It also isn’t under the control of the app developer at all, so if for instance they would prefer to jank (not produce a frame) instead of checkerboard when the scroll hits an unrasterized region of the page, they’re out of luck. It’s also ineffective if parts of the page that are pre-rasterized get invalidated by JavaScript -- now that pre-rasterized content is stale. It’s still useful to have around, since at least Chrome can display the pre-rasterized content until the new content is ready (this is the whole pending tree vs. active tree architecture; see the compositing design doc for an explanation), but it isn’t a replacement for fast rasterization. This is one of the (many) reasons motivating the move to GL-based rasterization (Ganesh), and when using Ganesh Chrome pre-paints only a very small buffer around the screen.\u003c/span\u003e\u003c/p\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003ch6 style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Checkerboarding-special-case:-low-resolution-tiles\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCheckerboarding special case: low resolution tiles\u003c/span\u003e\u003c/h6\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cbr /\u003e\u003c/p\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed\" style\u003d\"width:853px;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eYouTube Video\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-youtube\"\u003e\u003ciframe title\u003d\"YouTube video player\" class\u003d\"youtube-player\" type\u003d\"text/html\" src\u003d\"https://www.youtube.com/embed/RZfztPQfx6Y?rel\u003d0\u0026amp;wmode\u003dopaque\" frameborder\u003d\"0\" allowFullScreen\u003d\"true\" width\u003d\"853\" height\u003d\"480\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e Parts of the page displaying, but displaying at low resolution instead of high resolution.\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis is a “feature” of impl-side painting, designed mainly to gracefully handle pinch/zoom scenarios. Chrome will quickly rasterize large sections of the pending tree (i.e. the content that’s queued up to go on screen) at low resolution first, with the aim of at least showing \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esome\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ething. The cause here is identical to the cause of checkerboarding; this is essentially an intermediate state between having the content fully rasterized and not rasterized at all (checkerboard).\u003c/span\u003e\u003c/p\u003e\u003ch6 style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Checkerboarding-common-cause:-URL-bar-jank\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCheckerboarding common cause: URL bar jank\u003c/span\u003e\u003c/h6\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e Full-screen invalidations caused by the URL bar’s showing / hiding on scroll.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThere are times when Chrome doesn’t have a chance to rasterize enough content before a scroll gets to a region of the page (e.g. on very long pages), but for the most part impl-side painting handles static content well. As mentioned in the checkerboarding section, however, it copes poorly when the page is frequently invalidated by JavaScript. The resize event fired when the URL bar appears and disappears (per the current Chrome for Android omnibox UX) is a tragically common, totally unnecessary cause of invalidation on many mobile websites. Chrome itself has to do a re-layout to account for the additional pixels that just got added or subtracted from the total document height, but this is an optimized layout pass that shouldn’t (theoretically) cause full-document invalidations. Unfortunately many pages listen for the resize event, assume getting it means the page has actually changed dimensions dramatically as in the case of e.g. a rotation, and then modify their entire document’s style in response. This typically ends up looking exactly the same, but invalides everything as a result.\u003c/span\u003e\u003c/p\u003e\u003c/blockquote\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003ch5 style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Partial-content-during-network-load\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ci\u003ePartial content during network load\u003c/i\u003e\u003c/span\u003e\u003c/h5\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e When loading a web page from the network Chrome will attempt to render the page as quickly as possible, even if it doesn’t have all the required resources yet. This is a long-standing feature of the platform to let you read content as quickly as possible, and not technically jank, but is included for completeness.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eUnfortunately, it also looks significantly less polished than the style of many native applications, which show nothing (or a splash screen) until a basic UI shell is ready, and fill that shell in with data atomically when the data is ready. It’s possible to emulate this behavior on the web platform, and it looks much more polished to do so, but that’s unfortunately not a very common practice at this point.\u003c/span\u003e\u003c/p\u003e\u003c/blockquote\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Framerate\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFramerate\u003c/span\u003e\u003c/h3\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Low-sustained-framerate-during-any-kind-of-animation-janky-animations-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eLow sustained framerate during any kind of animation (“janky animations”)\u003c/span\u003e\u003c/h5\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed\" style\u003d\"width:853px;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eYouTube Video\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-youtube\"\u003e\u003ciframe title\u003d\"YouTube video player\" class\u003d\"youtube-player\" type\u003d\"text/html\" src\u003d\"https://www.youtube.com/embed/s-rBLTz0CMs?rel\u003d0\u0026amp;wmode\u003dopaque\" frameborder\u003d\"0\" allowFullScreen\u003d\"true\" width\u003d\"853\" height\u003d\"480\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e animation with a mostly-steady framerate that’s below 60Hz.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThere’s typically a consistent bottleneck in the system when this is the case, and about:tracing is designed for diagnosing exactly this case. If encountered, a standard trace (no need for Frame Viewer) of the low-framerate animation should show what operations are the long pole for the animation.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIt’s worth noting that there are two types of animation: those handled entirely by the compositor thread (so-called “accelerated” animations) and those that need to synchronously call into Blink or v8. The only type of accelerated animations are CSS animations (and CSS transitions and Web Animation) on opacity, transform, and certain CSS filters; plus scrolling and pinch/zoom. Everything else goes through Blink. Accelerated animations will never be bottlenecked on anything in the RendererMain thread, but non-accelerated animations can be.\u003c/span\u003e\u003c/p\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Delayed-beginning-to-any-animation\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eDelayed beginning to any animation\u003c/span\u003e\u003c/h5\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cbr /\u003e\u003c/p\u003e\u003cdiv /\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed\" style\u003d\"width:853px;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eYouTube Video\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-youtube\"\u003e\u003ciframe title\u003d\"YouTube video player\" class\u003d\"youtube-player\" type\u003d\"text/html\" src\u003d\"https://www.youtube.com/embed/MEhBK8Yuhko?rel\u003d0\u0026amp;wmode\u003dopaque\" frameborder\u003d\"0\" allowFullScreen\u003d\"true\" width\u003d\"853\" height\u003d\"480\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e a discernible pause between when an animation is meant to begin (e.g. in response to a finger tap) and when it actually begins. This is distinct from low framerate since sometimes the animation itself is fine, there’s just a pause before it starts.\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis is commonly caused by accelerated animations that are set up but require rasterization before beginning. E.g. creating a new layer and setting a CSS animation on its transform -- the animation will not start until the new layer is done being painted. The timeline delay here is designed to prevent animations beginning immediately only to drop a number of frames. The result is typically a much smoother-looking interaction overall, but it can be surprising.\u003c/span\u003e\u003c/p\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Low-framerate-during-to-swipe-input-throughput-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eLow framerate during to swipe input (throughput)\u003c/span\u003e\u003c/h5\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e special case of low-framerate animation, specifically when the animation is moving something in response to a touch movement. All touch-event-driven animations are non-accelerated animations.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eUnlike the delay at the beginning of an animation, which can be stretched out tens of milliseconds without the user really noticing, the only acceptable frame time for a running animation is the vsync interval (e.g. 16ms). Touch input can only be programmatically handled by JavaScript on the RendererMain thread, which means that \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eall \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003evisual touch-input-based effects are technically non-accelerated animations. Note that they can still avoid \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003epainting\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e by using an accelerated animation property, but they’ll subject to jank from all other activity on the main thread because the JavaScript input events can be blocked.\u003c/span\u003e\u003c/p\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Isolated-long-pauses-jank-during-JS-driven-animations-incl-touch-\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIsolated long pauses (“jank”) during JS-driven animations (incl touch)\u003c/span\u003e\u003c/h5\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e Single long pauses, rather than a consistent low framerate, during animations\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSometimes an animation is mostly fine, but stutters at one point. This is often harder to isolate, but about:tracing and the Dev Tools timeline are invaluable for figuring out what went wrong. Special cases of this include the delay at the beginning of animations. All non-accelerated animations are subject to jank of this type from any other activity on the Blink main thread (e.g. JavaScript timers executing).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Latency\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eLatency\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eLong input latency (rather than low framerate)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e Most jank is related to interruptions in frame production, but latency represents another class of problem manifesting as longer delays between input events entering the system and corresponding new frames being output. It’s possible to have a good / high framerate but bad / long latency\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSome examples of high latency are covered in the framerate examples, for instance delays at the beginning of an animation that’s kicked off in response to input. Generally if the entire pipeline takes long enough that it doesn’t fit into frame budget, we categorize it as a framerate rather than a latency issue. However, there are some edge cases where latency can be increased by seemingly unrelated issues.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-High-scrolling-latency-or-delays-beginning-scrolling-when-the-document-has-touch-event-handlers\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHigh scrolling latency or delays beginning scrolling when the document has touch event handlers\u003c/span\u003e\u003c/h5\u003e\u003cbr /\u003e\u003cdiv /\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-on sites-embed\" style\u003d\"width:853px;\"\u003e\u003ch4 class\u003d\"sites-embed-title\"\u003eYouTube Video\u003c/h4\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-youtube\"\u003e\u003ciframe title\u003d\"YouTube video player\" class\u003d\"youtube-player\" type\u003d\"text/html\" src\u003d\"https://www.youtube.com/embed/TUlU-y3gfAI?rel\u003d0\u0026amp;wmode\u003dopaque\" frameborder\u003d\"0\" allowFullScreen\u003d\"true\" width\u003d\"853\" height\u003d\"480\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e Calling preventDefault on a touch move event is spec’d to prevent scrolling from happening. Chrome therefore tries to give JavaScript a chance to run any registered touch move event handlers before scrolling the page. If JavaScript takes a while to respond, however, it can increase input latency during the scroll.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThere’s a delicate balance between honoring the contract with touch event handlers the page has registered and staying responsive. In particular, becuase JavaScript touch event handlers are stuck on the main thread with everything else, completely unrelated activity such as XHR parsing or style recalculation or JavaScript timers that run on the main thread will all block touch event handlers from running (none of these tasks currently yield, and as of this writing Blink’s entire event loop is a FIFO queue with no prioritization, although that’s changing with the advent of the Blink scheduler). The result is that if style recalculation runs for 100ms right when the user is dragging the page around, the scroll won’t move for 100ms until style recalc is finished, the touch event gets run and preventDefault \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003edoesn’t\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e get called during it.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNote that browser behavior here is wildly under-specified. Chrome’s behavior has evolved over time, and changed significantly recently with the advent of \u003c/span\u003e\u003ca href\u003d\"http://updates.html5rocks.com/2014/05/A-More-Compatible-Smoother-Touch\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003easynchronous touch move processing\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. One of the more egregious behavior hacks here is that Chrome typically gave touch events a ~200ms deadline to run, and if the event wasn’t processed by then it would get dropped and the page would scroll anyway. This was designed to preserve basic responsiveness even in the face of adversarial content.\u003c/span\u003e\u003c/p\u003e\u003ch5 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Scroll-linked-effects-out-of-sync\" /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Trebuchet MS;color:rgb(102,102,102);font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eScroll-linked effects out of sync\u003c/span\u003e\u003c/h5\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003ci\u003eBrief:\u003c/i\u003e visual effects linked to the scroll position can become 1-2 frames out of sync from the actual scroll\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis is somewhat complicated, but boils down to two different modes of operation in Chrome’s multi-stage rendering pipeline. In low-latency mode each stage of the pipeline will complete fast enough that \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;font-style:italic;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eall \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eof the stages complete within 16ms. If any of the stages run long, Chrome will fall out of low latency mode into high latency mode. At that point there will be an extra frame of latency in the entire rendering pipeline, which effectively increases frame budget by allowing thread parallelism but at the cost of latency.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNote that technically there is currently a low/high latency mode for both the main thread \u0026gt; compositor thread step and the compositor thread \u0026gt; browser UI thread step. The problem described here is specific to the main thread \u0026gt; compositor thread step.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe synchronization issue is that scrolling is a compositor-thread operation whereas the scroll-linked effects are necessarily main thread operations. This means that in high latency mode the main thread may be 1 frame behind the compositor thread, which means that the scroll position that the compositor is using to position the page and the scroll position Blink/JavaScript is currently aware of will be 1 step out of sync. Other than keeping the page in low latency mode by never blowing frame budget, there’s currently nothing a page can do about this.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIt’s also worth noting, though, that input latency is rarely a visible problem outside of these scroll-linked effects (like pull to refresh, or poorly implemented parallax, etc). The platform’s biggest problem remains that it’s incredibly difficult to maintain a high framerate.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3702888333079561327"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/anatomy-of-jank"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3682236115413041901"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"}],"author":[{}],"sites$pageName":{"$t":"anatomy-of-jank"},"sites$revision":{"$t":"23"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7326203891209963372"},"published":{"$t":"2014-09-11T21:18:10.922Z"},"updated":{"$t":"2014-09-11T21:45:44.510Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-11T21:45:43.135Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"The Rendering Critical Path"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eauthor: wiltzius@\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Rendering-Architecture-in-Brief\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eRendering Architecture in Brief\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-The-Critical-Rendering-Path\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eThe Critical Rendering Path\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Browser-Thread-Architecture\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eBrowser Thread Architecture\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Scrolling\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eScrolling\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Modifying-Style-of-Existing-DOM\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eModifying Style of Existing DOM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Adding-new-DOM\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eAdding new DOM\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Rendering-Architecture-in-Brief\" /\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eRendering Architecture in Brief\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eTo understand the symptoms and potential causes of jank, it's important to have a basic understanding of the browser's rendering pipeline. This article will briefly describe that pipeline assuming knowledge of the web platform but no knowledge of how the rendering engine works, with links to relevant design docs for more info.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis article is adapted from a similar section in \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer\"\u003eUsing Frame Viewer to Bust Jank\u003c/a\u003e. It goes into greater detail, but doesn't cover any examples. See that document for a\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003e more illustrated version of this process, which annotates a trace of an example style modification.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eWe'll focus on how the page is rendered \u003ci\u003eafter\u003c/i\u003e page load -- that is, how the browser handles screen updates in response to user input and JavaScript changes to the DOM. Rendering when loading a page is slightly different, as compromises to visual completeness are often made in order to get some content to appear faster; this is out of scope for this document which will focus on \u003ci\u003einteractive \u003c/i\u003erendering performance.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eMuch more detail about the specifics of how rendering inside of Blink works (i.e. the style, layout, and Blink paint systems), as well as a (somewhat dated) discussion of how it might evolve, can be found in the \u003ca href\u003d\"https://docs.google.com/a/chromium.org/document/d/1wYNK2q_8vQuhVSWyUHZMVPGELzI0CYJ07gTPWP1V1us/edit#heading\u003dh.6cdy1o585rsa\"\u003eRendering Pipeline doc\u003c/a\u003e. This document is intended to be more descriptive, higher-level, and include the related input and compositing systems.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-The-Critical-Rendering-Path\" /\u003e\u003cfont size\u003d\"3\"\u003eThe Critical Rendering Path\u003c/font\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eAfter loading, the page changes in response to two inputs: user interaction mediated by the user agent (default pressed button styles, scrolling, pinch/zooming, etc) and updates to the DOM made by JavaScript. From there, a cascade of effects through several rendering sub-systems eventually produces new pixels on the user’s screen.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr style\u003d\"line-height:normal\" /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eThe main subsystems are:\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr style\u003d\"line-height:normal\" /\u003e\u003c/font\u003e\u003c/p\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eInput handling [technically not related to graphics per se, but nevertheless critical for many interactions]\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eParsing, which turns a chunk of HTML into DOM nodes\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eStyle, which resolves CSS onto the DOM\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eLayout, which figures out where DOM elements end up relative to one another\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003ePaint setup, sometimes referred to as recording, which converts styled DOM elements into a display list (SkPicture) of drawing commands to paint later, on a per-layer basis\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003ePainting, which converts the SkPicture of drawing commands into pixels in a bitmap somewhere (either in system memory or on the GPU if using Ganesh)\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eCompositing, which assembles all layers into a final screen image\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eand, less obviously, the presentation infrastructure responsible for actually pushing a new frame to the OS (i.e. the browser UI and its compositor, the GPU process which actually communicates with the GL driver, etc).\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr style\u003d\"line-height:normal\" /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eAs an example, updating the innerHTML of a DOM element that’s visible on-screen will trigger work in every one of the systems above. In bad cases any one of them can cost tens of milliseconds (or more), meaning every one of them can be considered a liability for staying within frame budget -- that is, any one of these stages can be responsible for dropping frames and causing jank.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr style\u003d\"line-height:normal\" /\u003e\u003c/font\u003e\u003c/p\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Browser-Thread-Architecture\" /\u003e\u003cfont size\u003d\"3\"\u003eBrowser Thread Architecture\u003c/font\u003e\u003c/h3\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eThe browser has multiple threads, and because of the dependencies implied in the above pipeline which thread an operation runs on matters a lot when it comes to identifying performance bottlenecks. Style, layout, and some paint setup operations run on the renderer’s main thread, which is the same place that JavaScript runs. Parsing of new HTML from the network gets in own thread (in most cases), as does compositing and painting; however parsing of e.g. innerHTML is currently performed synchronously on the main thread.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr style\u003d\"line-height:normal\" /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eKeep in mind that JavaScript is single threaded and does not yield by default, which means that JavaScript events, style, and layout operations will block one another. That means if e.g. the style system is running, Javascript can’t receive new events. More obviously, it also means that other JavaScript events (such as a timer firing, or an XHR success callback, etc) will block JS events that may be very timely -- like touch events. NB this essentially means \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eapplications responding to touch input must consider the JavaScript main thread the application’s UI thread, and not block it for more than a few milliseconds\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eThe ordering of these events is often unfortunate, since currently Blink has a simple FIFO queue for all event types. The \u003ca href\u003d\"https://docs.google.com/a/chromium.org/document/d/11N2WTV3M0IkZ-kQlKWlBcwkOkKTCuLXGVNylK5E2zvc/edit\"\u003eBlink Scheduler project\u003c/a\u003e is seeking to add a better notion of priorities to this event queue. The scheduler will never be able to actually shorten non-yielding events, though, so is only part of the solution.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr style\u003d\"line-height:normal\" /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eIt's worth noting here that scrolling is “special” in that it happens outside of the main JavaScript context, and scroll positions are asynchronously reported back to the main thread and updated in the DOM. This prevents janky scrolling even if the page executes a lot of JavaScript, but it can get in the way if the page is well-behaved and wants to respond to scrolling.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIt's also worth noting that the pipeline above isn’t strictly hierarchically ordered -- that is, sometimes you can update style without needing to re-lay-out anything and without needing to repaint anything. A key example is CSS transforms, which don’t alter layout and hence can skip directly from style resolution (e.g. changing the transform offset) to compositing if the necessary content is already painted. The below sections note which stages are optional. \u003c/span\u003e\u003cspan style\u003d\"line-height:1.15;background-color:transparent\"\u003eDifferent types of screen updates require exercising different stages in the pipeline. \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003eOne way to keep animations inexpensive is to avoid stages of this pipeline altogether. The following sections cover a few common examples.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;line-height:17.25px;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eLastly, note that user interactions that the browser handles, rather than the application, are largely unexceptional: clicking a button changes its style (adding pseudo-classes) and those style changes need to be resolved and later stages of the pipeline run (e.g. the depressed button state needs to be painted, and then the page needs to be re-composited with that new painted content).\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Scrolling\" /\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eScrolling\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eUpdating the viewport's scroll position has been designed to be as cheap as possible, relying heavily on the compositing step and its associated GPU machinery.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eIn the simple case, when the user tries to scroll a page events flow through the browser as follows:\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eInput events are delivered to the browser process's UI thread\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eThe browser's gesture detector processing the input stream decides that the user is attempting to scroll the page content\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eInput events are sent directly from the browser UI thread to the compositor thread in the Renderer process (notably bypassing the Renderer's main thread, where JavaScript and Blink live)\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eOptionally, if there are touch event or mousewheel handlers registered on the part of the page being scrolled these events are added to Blink's event queue and the compositor will block further work on this frame until it receives an acknowledgment that those events have run and have not been preventDefault'd\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eThe compositor updates layer positions relative to the viewport\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:Arial;line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eOptionally, if newly exposed parts of the page have not been painted in previous frames, the compositor paints them.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:Arial;line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eOptionally, if newly exposed parts of the page have not been \u003ci\u003erecorded \u003c/i\u003ein previous frames, the compositor asks Blink to record new sections of DOM\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eThe compositor issues GL commands to the GPU process to recomposite painted textures on the GPU with the updated layer positions in step 4\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eThe compositor asynchronously sends a message to the Renderer's main thread with updated scroll position information.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eOptionally at this point updated JavaScript onScroll events can be fired by Blink\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eThis flow skips a lot of detail, which is covered in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/gpu-accelerated-compositing-in-chrome\"\u003eAccelerated Compositing design doc\u003c/a\u003e if you're curious.\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cp style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eImportant notes:\u003c/span\u003e\u003c/font\u003e\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eIn the common case, only compositing and the GPU infrastructure are exercised in producing a new frame during scrolling; all other steps are skipped.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eRegistering touch event handlers (see step 3.1) add those JavaScript touch event handlers as a synchronous step on the critical scrolling path.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Arial\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eThe compositor will almost always still produce frames even if its waiting on Blink for new content (e.g. for touch event handler acknowledgments in step 3.1, or for new recordings of DOM content in 4.1.1). Instead of the content it's trying to produce, it'll put up either old content that's already been painted in previous frames \u003c/span\u003e\u003ci style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eor\u003c/i\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003e if there's no such content available it'll put up a checkerboard pattern.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Modifying-Style-of-Existing-DOM\" /\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eModifying Style of Existing DOM\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap\"\u003eModifying the style of existing DOM elements from JavaScript (whether in response to input or not) will exercise most of the rendering pipeline, although it'll skip parsing. Depending on the styles modified, it may also skip layout and painting. Paul Irish and Paul Lewis have written a \u003c/span\u003e\u003ca href\u003d\"http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/\" style\u003d\"line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003egood article on html5rocks\u003c/a\u003e\u003cspan style\u003d\"line-height:17.25px;white-space:pre-wrap;background-color:transparent\"\u003e covering which styles affect which pipeline stages.\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eHere's an outline of how modifying style propagates through the browser:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eJavaScript runs, modifying some style (setting inline style, modifying a class list, etc). This may happen in a requestAnimationFrame callback, in an input event, in a timer callback, or anywhere else.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eWhen the compositor next asks Blink to paint part of the document, Blink will optionally recalculate style on any part of the DOM that it may need to paint.\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThis style recalculation is theoretically scoped to only the part of the DOM tree whose style is dirty, but in practice often includes the entire document (the Dev Tools timeline will show how many DOM nodes were operated on in each recalc style event).\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eOptionally, if the style recalculation has dirtied the layout of any elements that may need to be painted, layout is run on the relevant DOM subtree(s).\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eNotice the \"may\" in that sentence, since before layout is run and final element positions are known it isn't possible to tell what will be where. In practice, layouts often occur on the entire document. The Dev Tools timeline will show the root of the tree under operation for each layout event.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eOptionally, if any composited layer properties have changed (new composited layers, or new transforms or opacity of existing composited layers) the main-thread copy of the compositor layer tree is updated.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eNow whatever part of the document the compositor requested be painted can actually be painted, but note that this doesn't actually fill in pixels -- Blink here paints into a display list (currently an SkPicture).\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThis is step 6 in the overview of main subsystems above, often called SkPicture recording.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eNew SkPictures and the updated compositor layer tree are transferred from the main thread to the compositor thread (the so-called \"commit\")\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThe compositor prioritizes all content tiles and decides if any tiles need to be re-rastered (i.e. actually painted) to put up this new content\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThe compositor then paints these tiles\u003c/font\u003e\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eWith software painting, this is done on a software raster worker thread\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eWith Ganesh aka GPU rasterization, this is done on the compositor thread itself, converting the display list into GL commands\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThe compositor then generates the GL commands to produce a new frame and hands this frame's information to its parent compositor in the browser\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThe browser compositor issues the GL commands for a new frame including the browser UI and the child compositor's content\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eImportant notes:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eIt's possible to trigger style recalculation or layout outside of the rendering pipeline by reading back CSS properties that are lazily computed. In the worst case script can enter a write / read loop where it sets a style, reads a property that forces synchronous layout or style recalculation, and then repeats this process. We call this layout thrashing; Wilson Page has written a \u003ca href\u003d\"http://wilsonpage.co.uk/preventing-layout-thrashing/\" rel\u003d\"nofollow\"\u003egood article on the subject\u003c/a\u003e.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003eThis flow summarizes a lot of detail, again covered in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/gpu-accelerated-compositing-in-chrome\"\u003eAccelerated Compositing design doc\u003c/a\u003e.\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Adding-new-DOM\" /\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eAdding new DOM\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/p\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003eAdding new DOM or replacing a DOM subtree requires parsing the new DOM. Whether this parsing happens synchronously on the main thread or asynchronously off-thread depends on how the DOM is inserted. An incomplete listing:\u003c/font\u003e\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eXHR responses are currently processed on the main thread; crbug.com/402261 tracks work to make it asynchronous\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:1.15;background-color:transparent\"\u003eSetting the srcdoc of an iframe is asynchronous, see crbug.com/\u003c/span\u003e\u003cspan style\u003d\"line-height:15.3333320617676px\"\u003e308321 for the work that made this possible\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"line-height:15.3333320617676px\"\u003e\u003cfont size\u003d\"2\"\u003edata: URLs are always asynchronously parsed; https://codereview.chromium.org/210253003 for the work that made this possible\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"line-height:1.15;background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eDuring page load, most parsing is done asynchronously using the threaded parser\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cfont size\u003d\"2\"\u003eAfter parsing, rendering proceeds roughly as above in \"modifying style of existing DOM\"\u003c/font\u003e\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/the-rendering-critical-path"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7326203891209963372"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7326203891209963372"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7326203891209963372"}],"author":[{}],"sites$pageName":{"$t":"the-rendering-critical-path"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8355938783792304247"},"published":{"$t":"2014-09-10T21:53:46.756Z"},"updated":{"$t":"2014-09-10T21:53:46.781Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-10T21:53:46.756Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"mov1.mp4"},"summary":{},"content":{"type":"video/mp4","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8355938783792304247"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"},{"rel":"alternate","type":"video/mp4","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/anatomy-of-jank/mov1.mp4"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8355938783792304247"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8355938783792304247"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8355938783792304247"},{"rel":"edit-media","type":"video/mp4","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8355938783792304247"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5753995428063010938"},"published":{"$t":"2014-09-10T21:53:44.073Z"},"updated":{"$t":"2014-09-10T21:53:44.095Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-10T21:53:44.073Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"mov2.mp4"},"summary":{},"content":{"type":"video/mp4","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5753995428063010938"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"},{"rel":"alternate","type":"video/mp4","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/anatomy-of-jank/mov2.mp4"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5753995428063010938"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5753995428063010938"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5753995428063010938"},{"rel":"edit-media","type":"video/mp4","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5753995428063010938"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8675327716497776312"},"published":{"$t":"2014-09-10T21:53:41.199Z"},"updated":{"$t":"2014-09-10T21:53:41.224Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-10T21:53:41.199Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"mov3.mp4"},"summary":{},"content":{"type":"video/mp4","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8675327716497776312"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"},{"rel":"alternate","type":"video/mp4","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/anatomy-of-jank/mov3.mp4"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8675327716497776312"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8675327716497776312"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8675327716497776312"},{"rel":"edit-media","type":"video/mp4","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8675327716497776312"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5597186595120983210"},"published":{"$t":"2014-09-10T21:53:39.377Z"},"updated":{"$t":"2014-09-10T21:53:39.403Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-10T21:53:39.377Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"mov4.mp4"},"summary":{},"content":{"type":"video/mp4","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5597186595120983210"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3682236115413041901"},{"rel":"alternate","type":"video/mp4","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/anatomy-of-jank/mov4.mp4"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5597186595120983210"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5597186595120983210"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5597186595120983210"},{"rel":"edit-media","type":"video/mp4","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5597186595120983210"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDUpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5467815236996308114"},"published":{"$t":"2010-03-16T22:35:09.684Z"},"updated":{"$t":"2014-09-06T02:13:42.248Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-06T02:13:41.023Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Firmware Verified Boot Crypto Specification"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"font-family:Verdana\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Abstract\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eAbstract\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Design_Principles_and_Pitfalls_8677765503525734\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eDesign principles and pitfalls\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Background_9948604376986623_76\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003eBackground\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#How_cryptographic_signature_ve\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eHow cryptographic signature verification works\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Root_Keys_and_Signing_Keys_336_2005125042051077\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eRoot keys and signing keys\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Preventing_Rollback_Attacks_32_9610213935375214\"\u003e\u003cstrong\u003e2.1.1 \u003c/strong\u003ePreventing rollback attacks\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Speed_and_bottleneck_considera\"\u003e\u003cstrong\u003e2.1.2 \u003c/strong\u003eSpeed and bottleneck considerations\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Putting_it_all_together_Crypto_002011277712881565\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003ePutting it all together: Crypto Architecture\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Kernel_level_verification\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eKernel-level verification\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Lifetime_of_the_Root_Key_7646217057481408\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eLifetime of the root key\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#What_crypto_implementations_ne_4928052546456456\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003eWhat crypto implementations need to be a part of the R/O firmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Other_Crypto_Issues_9152098940_9233817029744387\"\u003e\u003cstrong\u003e2.6 \u003c/strong\u003eOther considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#What_key_size_is_enough_for_th_13512184657156467\"\u003e\u003cstrong\u003e2.6.1 \u003c/strong\u003eWhat key size is enough for the root key and signing key?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#RSA_Padding_7247870247811079_9_9370813267305493\"\u003e\u003cstrong\u003e2.6.2 \u003c/strong\u003eRSA padding \u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#What_is_the_TPM_used_for_14809_872982325963676\"\u003e\u003cstrong\u003e2.6.3 \u003c/strong\u003eWhat is the TPM used for?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#Functional_Tests_and_Hardware_\"\u003e\u003cstrong\u003e2.7 \u003c/strong\u003eFunctional tests and hardware qualifications \u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"TOC-Abstract\" /\u003eAbstract\u003c/h3\u003e\u003cfont size\u003d\"2\"\u003eThis document describes the cryptographic primitives and building blocks used for implementing verified boot in the firmware. The document is primarily targeted at Google Chrome OS-based devices running Google-signed firmware and software. Chromium OS devices may use similar verified boot schemes with their own (non-Google-signed) chain of trust. We want to emphasize this does not prevent devices based on the open source Chromium OS project from having their own firmware. The goal here is to assure customers of Google Chrome OS devices that they are actually running Google Chrome OS. \u003c/font\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Design_Principles_and_Pitfalls_8677765503525734\" /\u003eDesign principles and pitfalls\u003c/h3\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eSince we are in firmware land, the cost of changing the architecture after an implementation is high! Cost varies from \"unfixable\" for the boot stub to \"need a firmware update\" for the writable firmware and the algorithm for verifying the kernel.  \u003c/font\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px;text-align:left\"\u003e\u003cfont size\u003d\"2\"\u003eChoose a conservative and simple design. \u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eHave the design reviewed by experts. (Review first, implement later.)\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eSecurity doesn't come for free. We want to minimize the performance overhead as much as possible.\u003c/font\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eIn the context of this document, the main performance concern is minimizing time to boot, or more specifically, the time taken to pass control to a trusted Chrome OS kernel. \u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eUse well understood cryptographic building blocks instead of designing new ones.\u003c/font\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eCryptography is hard to understand, even harder to get right.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eUse well known and studied crypto primitives (RSA, SHA, AES, etc.) and protocols (public-key signatures).\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Background_9948604376986623_76\" /\u003eBackground\u003c/h3\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe firmware is the lowest level of software that runs on a system. In Chrome OS devices, the firmware is responsible for initializing the main application processor along with RAM, embedded controllers, chipsets, etc. In certain architectures, e.g. ARM, a separate modem processor is responsible for initializing the main processor. Parts of the firmware are \u003ci\u003eread-only \u003c/i\u003e(at the lower layers).  This code is baked into the firmware during production and can't be changed. The rest of the firmware is field upgradable. The proposed mechanisms for such updates are described in a separate document. At the boundary of \u003ci\u003eread-only\u003c/i\u003e to \u003ci\u003eread-write\u003c/i\u003e firmware, the verified boot mechanism (firmware-land) kicks in. It is responsible for verifying that the next piece of code is signed by Google for Google Chrome OS devices. The goal here is to provide a boot path to end users which provides assurances\u003cb\u003e \u003c/b\u003ethat they are running known good code. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eImportant note:\u003c/b\u003e To reemphasize the point made in the \u003ca href\u003d\"http://www.chromium.org/chromium-os/chromiumos-design-docs/verified-boot\" title\u003d\"Verified Boot\"\u003eVerified Boot\u003c/a\u003e design document, we are \u003cb\u003enot \u003c/b\u003e\u003ci\u003epreventing \u003c/i\u003eusers from running \u003ci\u003eany\u003c/i\u003e operating system they please, only to provide a mechanism that guarantees that a Chrome OS device is running the authentic Google Chrome OS. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch2 style\u003d\"font-size:14pt\"\u003e\u003ca name\u003d\"How_cryptographic_signature_ve\" /\u003e\u003cb\u003eHow cryptographic signature verification works\u003c/b\u003e\u003c/h2\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThis section presents a small primer on how signature verification is designed to work in our context. We use public-key cryptography: each key is actually a keypair with public and private key components. Data encrypted by the private key can be decrypted by the public key and vice versa. In all cases, the private key component is known only to Google. The public key is used by the firmware for performing the verification. A simple implementation would be for Google to encrypt an entire r/w firmware component with the private key, and for the firmware to use the corresponding pre-baked public key to decrypt the firmware and continue execution (if decryption is successful). However, public-key cryptography is sloooow, and moreover, we are not interested in the confidentiality of the firmware component, only that any code we execute in the verified boot path is authenticated. Therefore, we use the concept of cryptographic signatures. Public-key signatures combine message digests (such as SHA-1) with public-key cryptography. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eA message digest of a message \u003ci\u003em\u003c/i\u003e maps the message to a fixed size hash value \u003ci\u003eH(m)\u003c/i\u003e. A cryptographic message digest has two essential properties:\u003c/font\u003e\u003c/div\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eCollision resistance: Two different messages are highly unlikely to map to the same hash value.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eIrreversibility: Given a hash value, it's computationally infeasible to generate a message \u003ci\u003em\u003c/i\u003e which hashes to that value.  \u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eHere are the steps for firmware verification:\u003c/font\u003e\u003c/div\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eFor a firmware component blob \u003ci\u003eF\u003c/i\u003e, Google generates a signature \u003ci\u003eS(F) \u003c/i\u003e\u003d \u003ci\u003eRSA_privatekey(H(F))\u003c/i\u003e, where \u003ci\u003eH\u003c/i\u003e is the message digest function. \u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe firmware verification routine takes \u003ci\u003eF\u003c/i\u003e and \u003ci\u003eS(F)\u003c/i\u003e as input, computes \u003ci\u003eH(F)\u003c/i\u003e and verifies that \u003ci\u003eH(F)\u003c/i\u003e \u003d\u003d \u003ci\u003eRSA_publickey(S(F)).\u003c/i\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe security of the above scheme depends on two key factors: \u003c/font\u003e\u003c/div\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe firmware verification routine uses the \u003ci\u003ecorrect \u003c/i\u003epublic key on the attached signature to get the expected hash value. \u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eOnly Google can generate a signature that successfully verifies using the \"correct\" public key.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eWe ensure that the correct public key is used by putting the public key in the read only part of the firmware. It doesn't matter if it can be read by an attacker, since it only allows for verifying an existing signature. We ensure that the signature is generated by Google by keeping the private key known only to Google, so only Google can generate a valid signature on a blob of data. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003eHere's a table listing various hashing and signature verification algorithms, including their speed as measured by invoking \"openssl speed\" on a typical netbook.\u003cbr /\u003e\u003cbr /\u003e\u003ctable border\u003d\"1\" bordercolor\u003d\"#000000\" cellpadding\u003d\"3\" cellspacing\u003d\"0\" style\u003d\"font-size:1em;line-height:inherit;border-collapse:collapse\" width\u003d\"100%\"\u003e\u003ctbody\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003e\u003cb\u003eAlgorithm\u003c/b\u003e\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e\u003cb\u003eSpeed\u003c/b\u003e\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e\u003cb\u003eNote\u003c/b\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003eRSA-1024\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e0.4ms/verification\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003eNIST recommends not to be used after 2010\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003eRSA-2048\u003cbr /\u003e\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e1.28ms/verification\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003eNIST recommended for use after 2010\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003eRSA-4096\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e4.5ms/verification\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003eNIST recommended for use after 2010\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003e\u003cfont color\u003d\"#999999\"\u003eMD5\u003c/font\u003e\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e\u003cfont color\u003d\"#999999\"\u003e256MB/s*\u003c/font\u003e\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e\u003cfont color\u003d\"#999999\"\u003eConsidered Unsafe\u003c/font\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003eSHA-1\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e111MB/s*\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003eRecent attacks suggest its collision resistance is lesser than previously thought (80-bits)\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003eSHA-256\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e26MB/s*\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003eNIST recommended for use after 2010\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"text-align:left\"\u003e\u003ctd width\u003d\"33%\"\u003eSHA-512\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e27MB/s*\u003c/td\u003e\u003ctd width\u003d\"33%\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e* - 8192 byte blocks.\u003cbr /\u003e\u003cbr /\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Root_Keys_and_Signing_Keys_336_2005125042051077\" /\u003eRoot keys and signing keys\u003c/h3\u003eSince signature verification comes with an additional overhead, we can't simply choose to use the strongest available verification algorithm for the whole verified boot process. However, we need to start with a strong enough algorithm to protect Chrome OS devices for their expected lifetime. For long-term use, NIST recommends using \u003ci\u003eat least\u003c/i\u003e \u003ca href\u003d\"http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf\" target\u003d\"_blank\" title\u003d\"RSA-2048 and SHA-256\" rel\u003d\"nofollow\"\u003eRSA-2048 and SHA-256\u003c/a\u003e. Therefore, we plan on using a combination of a stronger root key and weaker signing keys. We will use a strongest available algorithm (within practical speed constraints) to sign an initial key. Subsequent stages of the verified boot will use the weaker (but faster) algorithms for verification.\u003cbr /\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eIf one of the weaker algorithms or signing keys used for verification of these subsequent stages is cracked/broken, a new firmware or software update can be issued that uses a different signing key and/or a stronger algorithm.\u003cbr /\u003e\u003cbr /\u003e\u003ch4 style\u003d\"font-size:10pt\"\u003e\u003ca name\u003d\"Preventing_Rollback_Attacks_32_9610213935375214\" /\u003e\u003cb\u003ePreventing rollback attacks\u003c/b\u003e\u003c/h4\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eTo prevent rollback attacks, where an attacker may try to to update a Google Chrome OS device with an older signed firmware that has a known vulnerability, each signing key has a strictly increasing associated \u003cb\u003eKey Version#\u003c/b\u003e. The read-only firmware writes the highest \u003cb\u003eKey Version#\u003c/b\u003e so far into an NVRAM location, in the TPM chip. This NVRAM location is lockable, such that only the read-only firmware can write to it, and can't be overwritten by any other firmware component or the operating system. During the verified boot process, the read-only firmware refuses to pass control to a signed firmware block that uses a signing key with an index smaller than the highest seen so far. In addition, since we have two firmware copies, this index can be updated whenever min(Key#A, Key#B) changes. This allows the device to survive a failed firmware update. On successful boot with the new firmware, the previous copy of the firmware is overwritten by the new one, the highest signing key index is updated, and any further rollbacks are prevented.\u003c/div\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eIn addition to the \u003cb\u003eKey Version#\u003c/b\u003e associated with each key, each firmware update has an associated \u003cb\u003eFirmware Version#\u003c/b\u003e. The R/O firmware also keeps track of this in a non-volatile location similar to the Key Version# to prevent rollbacks to an older R/W firmware. Note that these two numbers serve different purposes:\u003c/div\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eKey Version# prevents key rollbacks (use of an older invalidated signing key that might have been compromised to sign a firmware)\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eFirmware Version# prevents firmware rollbacks (use of an older signed firmware update that might have known vulnerabilities)\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003ch4 style\u003d\"font-size:10pt\"\u003e\u003ca name\u003d\"Speed_and_bottleneck_considera\" /\u003e\u003cb\u003eSpeed and bottleneck considerations\u003c/b\u003e\u003c/h4\u003eAlthough public key signature verification is an expensive operation, we expect the main bottleneck to be hash computation of blocks of data that need to be verified. In addition, verification will likely happen just a few times for each final hash value that is computed. Given these tradeoffs, it's likely that we'll still be able to use the stronger verification algorithm (for example, RSA-2048 below) once we switch to using the signing key for verification, but we'll need to switch to a weaker hashing algorithm (SHA-1), that is, start with RSA-4096+SHA-512, then switch to RSA-2048+SHA-1. This tradeoff can be revisited and analyzed in more detail once we have some hard numbers from an actual verified boot implementation.\u003cbr /\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Putting_it_all_together_Crypto_002011277712881565\" /\u003ePutting it all together: Crypto Architecture\u003c/h3\u003e\u003c/span\u003e\u003cspan\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-crypto/cryptospecs.webp?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1381341119111/chromium-os/chromiumos-design-docs/verified-boot-crypto/cryptospecs.webp\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Verdana\"\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003eFor \u003cb\u003eHeader H:\u003c/b\u003e\u003c/font\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eLength\u003c/b\u003e, is a fixed-width field and equals the length of H\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eAlgorithm\u003c/b\u003e is a fixed-width field integer that specifies the key size and hashing algorithm to use for verifying signatures using the signing key.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eSigning Key\u003c/b\u003e is the signing key used for the rest of the firmware.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eKey Version#\u003c/b\u003e is the rollback index associated with the \u003cb\u003eSigning Key\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eCrypto Hash\u003c/b\u003e is a fixed-width field that contains the cryptographic hash of the rest of the header \u003cb\u003eH(Len || Algorithm || Signing Key || Key Version#).\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eSignature \u003cb\u003eS_root \u003d RSA_Sign(\u003cfont color\u003d\"#0000FF\"\u003eRoot Key\u003c/font\u003e, H)\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003eThe signature for the R/W firmware is split into two:\u003c/font\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eSignature \u003cb\u003eS_signing#1\u003c/b\u003e \u003d \u003cb\u003eRSA_Sign\u003c/b\u003e(\u003cb\u003e\u003cfont color\u003d\"#0000FF\"\u003eSigning Key\u003c/font\u003e\u003c/b\u003e, \u003cb\u003eFirmware Version# | Len | Preamble\u003c/b\u003e)\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eSignature \u003cb\u003eS_signing#2\u003c/b\u003e \u003d \u003cb\u003eRSA_Sign\u003c/b\u003e(\u003cfont color\u003d\"#0000FF\"\u003e\u003cb\u003eSigning Key\u003c/b\u003e,\u003c/font\u003e \u003cb\u003eR/W Firmware Data\u003c/b\u003e).\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cfont size\u003d\"2\"\u003eThis signature helps in verifying the length field and the Firmware rollback early in the verification process. \u003cbr /\u003e\u003c/font\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003eFor rollback protection, we have a pair of indices: the \u003cb\u003eKey Version# (K#)\u003c/b\u003e and the \u003cb\u003eFirmware Version# (F#)\u003c/b\u003e. K# is updated whenever the signing key is changed—either if it's past its lifetime (\u003ci\u003eY\u003c/i\u003e months) or if it has been compromised. F# is incremented with each update. Logically, the combination of K# and F# uniquely identifies the version of an update. The update process will \u003cb\u003erefuse to update if either of the following conditions is TRUE\u003c/b\u003e: \u003c/font\u003e\u003cbr /\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eK# \u003d\u003d  stored K#, but F#  \u0026lt; stored F#\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eK# \u0026lt; stored K#\u003c/li\u003e\u003c/ol\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cbr /\u003eHaving separate key version and firmware version rollback prevention indices allows for generating new firmware updates without the need to generate a new signing key each time (which in turn requires getting the root key out of secure storage). This way, firmware updates are protected against rollbacks even if the signing key stays the same.\u003cbr /\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px\"\u003eThe steps performed by the read-only firmware are as follows:\u003c/p\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eVerify the signing key signature is valid\u003cbr /\u003e- If RSA_Verify(\u003cb\u003e\u003cfont color\u003d\"#0000FF\"\u003eRoot Key\u003c/font\u003e\u003c/b\u003e,\u003cb\u003e H\u003c/b\u003e) fails, Go to \u003c/font\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eStep 7 \u003c/b\u003e(Failure).\u003cbr /\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eVerify that this is not a \u003cb\u003ekey rollback \u003c/b\u003e\u003cbr /\u003e- If K# \u0026lt; Stored K#, go to \u003c/font\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eStep 7 \u003c/b\u003e(Failure).\u003cb\u003e \u003c/b\u003e\u003c/font\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e- else, Stored K# \u003d K#, lock Stored Key# to prevent write access\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eVerify that this is not a \u003cb\u003efirmware rollback \u003c/b\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003e- \u003c/b\u003eIf F# \u0026lt; Stored F#, go to \u003c/font\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eStep 7\u003c/b\u003e  (Failure).\u003cbr /\u003e- else, Stored F# \u003d F#, lock Stored F# to prevent write access\u003c/font\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eDetermine signing key algorithm to use from \"Algorithm.\" For now, let's assume we decide to go with RSA-1024 and SHA-1.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eFrom here on, the rest of the verification is performed using the signing key and algorithm\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003e- For example, To verify a firmware blob F, do RSA_Verify(\u003cfont color\u003d\"#0000FF\"\u003e\u003cb\u003eSigning Key\u003c/b\u003e\u003c/font\u003e, \u003cb\u003eF\u003c/b\u003e). If NOT, Go to \u003c/font\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eStep 7.  \u003c/b\u003e\u003c/font\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont color\u003d\"#0000ff\"\u003e\u003cfont size\u003d\"2\"\u003eSuccess\u003c/font\u003e\u003c/font\u003e\u003cfont size\u003d\"2\"\u003e - Continue with \u003cb\u003ekernel level verification\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont color\u003d\"#cc0000\"\u003eFailure -\u003c/font\u003eIf this is firmware-A, repeat above steps with firmware-B. If firmware-B is bad, \u003cfont color\u003d\"#FF0000\"\u003ego to recovery!!\u003c/font\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003eNote that, for both the root key and signing key, only the public part of the key is exposed. This ensures that only Google can generate S_root and S_signing. \u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Kernel_level_verification\" /\u003e\u003cb\u003eKernel-level verification\u003c/b\u003e\u003c/h3\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px\"\u003eOnce the R/W firmware has been verified, the next step is for the R/W firmware to verify the kernel before passing control to it. There are a few possible options here:\u003c/p\u003e\u003cbr /\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eUse a different signing key just for kernel signing. This key must be verified by the R/W firmware signing key.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eUse the R/W firmware signing key for verifying the kernel.\u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px\"\u003eThe main disadvantage of option 1 is the extra verification step required for verifying the kernel signing key. In addition, a separate rollback key index must stored for the kernel signing key.\u003c/p\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe main disadvantage of option 2\u003cb\u003e \u003c/b\u003eis that now any kernel update must be accompanied by a firmware update with a new signing key (for preventing rollback). \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eAs a firmware update is much more time consuming and disruptive than a kernel update, we chose option 1 (use a different signing key just for kernel signing).\u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003eIn addition, the kernel is stored on the disk and it needs to be retrieved by parsing the partition table. Currently, there is no cryptographic verification of the partition table. However, the firmware code does a strict checking of the partition table (e.g. ensuring there are no overlapping partitions) and outright rejects partition tables that do not look right. \u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eNote also that since this happens in the R/W firmware, the verification mechanism can change over time and with autoupdates.\u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Lifetime_of_the_Root_Key_7646217057481408\" /\u003eLifetime of the root key\u003c/h3\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eSince the root key is baked into the read-only firmware at manufacture, it can't be changed once a Chrome OS device leaves the factory. Since any update to this key requires changes during manufacture, these will be changed once every four years. Since the root keys have a much larger lifetime than the signing keys, they will be of higher strength (4096 bit RSA keys or higher). The signing key to use for pushing an update to a device can be determined via the SKU. Newer SKUs will use the newer root key chain of trust. \u003c/div\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"What_crypto_implementations_ne_4928052546456456\" /\u003eWhat crypto implementations need to be a part of the R/O firmware\u003c/h3\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eIdeally, due to firmware size limitations, goals for minimal complexity, and the inability to update in the field, we'd like to limit the functionality implemented in the the read-only firmware to the bare essentials. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eAt the very least, the read-only firmware needs to implement the following: \u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eRSA Signature Verification (for combinations of various 1024-8192 bit key sizes and SHA-1/256/512 message digest algorithms)\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eSHA-1/256/512 Hashing\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eA way to write and lock a portion of the NVRAM such that it can't be written to by any other component\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eItems 1 and 2 are required to verify the signing key. Item 3 is required to \u003ca href\u003d\"https://docs.google.com/a/google.com/Doc?docid\u003d0AWwzXTHj7UwzZGhtOHZwNHJfMTNnaHc1cHNmNA\u0026amp;hl\u003den#Preventing_Rollback_Attacks_32\" title\u003d\"prevent key rollback attacks\"\u003eprevent rollback attacks\u003c/a\u003e. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe weaker (relatively) crypto algorithms used by the signing keys \u003cb\u003emay \u003c/b\u003ebe implemented in the R/W firmware. However, there are risks to consider here:\u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eThe algorithm implementations on the R/W firmware also needs to be verified by the R/O firmware, a task that results in additional overhead. \u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eAdditional complexity is required in the R/O firmware for memory mapping these algorithms for use by the rest of the firmware. \u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003eTo avoid the additional complexity involved in having the algorithm implementations in the R/W firmware, we currently plan on having the R/O firmware implement all of SHA-1/256/512 and RSA-1024/2048/4096/8192. Although R/O firmware size may be a constraint, the variants within each class of algorithms (SHA-256 and SHA-512, for example) are similar, and there should be some opportunity for code reuse between them.\u003cbr /\u003e\u003cbr /\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Other_Crypto_Issues_9152098940_9233817029744387\" /\u003e\u003cfont size\u003d\"3\"\u003eOther considerations\u003c/font\u003e\u003c/h3\u003e\u003ch4 style\u003d\"font-size:10pt\"\u003e\u003ca name\u003d\"What_key_size_is_enough_for_th_13512184657156467\" /\u003eWhat key size is enough for the root key and signing key?\u003c/h4\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eNIST \u003ca href\u003d\"http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57_part1_rev3_general.pdf\" target\u003d\"_blank\" title\u003d\"recommends\" rel\u003d\"nofollow\"\u003erecommends\u003c/a\u003e the use of RSA 2048/SHA-256 or higher as the signature algorithm for use after 12/31/2010. Our plan is to use a 8192-bit RSA key with SHA-512 for the root key signatures.\u003c/div\u003e\u003cbr /\u003eThe security of RSA derives from the computational difficulty of factoring very large numbers into its prime factors. The best known current algorithm for factoring large numbers is the Number Field Sieve (NFS). The runtime of NFS scales as e\u003csup\u003e\u003ci\u003ec\u003c/i\u003e \u003ci\u003en\u003c/i\u003e^1/3 (log\u003c/sup\u003e\u003csub\u003e2\u003c/sub\u003e\u003csup\u003e \u003ci\u003en\u003c/i\u003e)^2/3\u003c/sup\u003e, where \u003ci\u003en\u003c/i\u003e is the size of the number in bits and \u003ci\u003ec\u003c/i\u003e is typically 1.5-2.\u003cbr /\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eFor the root key, we plan to use a 8192-bit RSA key. Note that, based on the runtime scaling of the Number Field Sieve, it takes at least 1.429206 x 10\u003csup\u003e24 \u003c/sup\u003e more computational effort to factor a 4096-bit number than a 1024-bit number. As a reference, the general-purpose factoring record is for the 664-bit RSA200 number which took the equivalent of 55 2.2GHz Opteron CPU years for the sieving step of NFS and an additional 3 months on an 80 2.2GHz Opteron CPU cluster for the matrix steps.\u003c/div\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eFor signing keys, we have considerable more flexibility, since the key size or the keys themselves can be changed with future system update. Since these keys will change/rotate often, we plan to use 1024-bit RSA keys which provides a good speed/performance trade-off.\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e \u003cbr /\u003e\u003ch4 style\u003d\"font-size:10pt\"\u003e\u003ca name\u003d\"RSA_Padding_7247870247811079_9_9370813267305493\" /\u003eRSA padding \u003c/h4\u003eRSA operations during signature operations are not directly performed on the raw cryptographic hashes but rather on a padded/extended version of the cryptographic hash. We intend to use the standard padding/extension function for this. There are two padding schemes specified by PKCS#1 v2.1 standard - PKCS1.5 and PSS. Although PKCS#1 recommends phasing out PKCS1.5 (certain attacks were discovered against faulty implementations) in favor of PSS, PSS is more complex to implement. PSS requires the use of a PRNG. So if PSS padding is used, a crypto-grade PRNG will also need to be implemented as part of the read-only firmware. Currently, we plan on using PKCS1.5 padding since its implementation is much simpler.\u003cbr /\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003ch4 style\u003d\"font-size:10pt\"\u003e\u003ca name\u003d\"What_is_the_TPM_used_for_14809_872982325963676\" /\u003e\u003cb\u003e\u003cb\u003eWhat is the TPM used for?\u003c/b\u003e\u003c/b\u003e\u003c/h4\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eFor verified boot, we do not use the TPM for performing cryptographic operations, since TPM chips are not necessarily crypto-accelerator devices, and there is no speed advantage. We use the TPM as secure non-volatile storage for preventing key rollback attacks. The TCG TPM standard (v1.2 rev103) includes two mechanisms that we may use for storing monotonically increasing integers in a runtime, tamper-resistant fashion: \u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003cul style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eNVRAM regions that may be locked and written to prior to TPM ownership assertion\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eMonotonically increasing counters\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eWe use NVRAM regions in the TPM and write the counters to that space.  This area is only writable at firmware read-only boot time and during recovery mode.\u003c/div\u003e\u003cbr /\u003e\u003ch3 style\u003d\"font-size:12pt\"\u003e\u003ca name\u003d\"Functional_Tests_and_Hardware_\" /\u003e\u003cb\u003eFunctional tests and hardware qualifications \u003c/b\u003e\u003c/h3\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eFor firmware vendors, we have a suite of functional tests to test their implementations. This includes testing crypto blocks like RSA, SHA, as well as crypto primitives like signature checking. \u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003eFor hardware qualification tests, here are examples of tests we use:\u003c/font\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003col style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eRoot Key Verification Test:\u003c/b\u003e Provide firmware where the signing key cannot be verified by using the root key (S_root is invalid). \u003cbr /\u003e\u003cb\u003eExpected Output:\u003c/b\u003e Device should refuse to use the firmware, jump to Recovery.\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eRollback Prevention Test:\u003c/b\u003e Provide firmware where the signing key# is less or equal to S_high.\u003cbr /\u003e\u003cb\u003eExpected Output:\u003c/b\u003e Device should refuse to use old firmware, jump to Recovery. \u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eSigning Key Verification Test:\u003c/b\u003e Provide firmware where the verification of F using the signing key fails (S_signing is invalid).\u003cbr /\u003e\u003cb\u003eExpected Output: \u003c/b\u003eDevice should refuse to use the firmware, jump to Recovery.\u003c/font\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003eMore details can be found in the documentation for the Semi-automated Firmware Testing Framework (\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/for-testers/saft\"\u003eSAFT\u003c/a\u003e).\u003c/div\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-crypto"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5467815236996308114"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5467815236996308114"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5467815236996308114"}],"author":[{"name":{"$t":"Kan Liu"},"email":{"$t":"kanliu@chromium.org"}}],"sites$pageName":{"$t":"verified-boot-crypto"},"sites$revision":{"$t":"9"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5831823228453817015"},"published":{"$t":"2013-08-06T14:07:18.368Z"},"updated":{"$t":"2014-09-04T16:09:01.691Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-04T16:09:00.397Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"HTTP/2"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2 style\u003d\"margin:1em 0px 15px;line-height:1.7;font-size:2em;padding:0px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:Helvetica,arial,freesans,clean,sans-serif\"\u003e\u003ca name\u003d\"TOC-Instructions\" /\u003e\u003cspan style\u003d\"font-size:2em;line-height:1.7;font-weight:normal;background-color:transparent\"\u003eInstructions\u003c/span\u003e\u003c/h2\u003e\u003col style\u003d\"padding:0px 0px 0px 30px;margin-top:15px;margin-right:0px;margin-left:0px;margin-bottom:0px!important\"\u003e\u003cli style\u003d\"color:rgb(51,51,51);font-family:Helvetica,arial,freesans,clean,sans-serif;font-size:15px;line-height:25px\"\u003e\u003cp style\u003d\"margin:15px 0px\"\u003eGet and build the latest Chromium source: \u003ca href\u003d\"https://code.google.com/p/chromium/wiki/UsingGit\" style\u003d\"color:rgb(65,131,196);text-decoration:none\"\u003ehttps://code.google.com/p/chromium/wiki/UsingGit\u003c/a\u003e, \u003cspan style\u003d\"font-size:15px;background-color:transparent\"\u003e\u003cb\u003eOR\u003c/b\u003e join the \u003ca href\u003d\"https://www.google.com/intl/en/chrome/browser/canary.html\"\u003eChrome Canary\u003c/a\u003e channel. \u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli\u003e\u003cp style\u003d\"color:rgb(51,51,51);font-family:Helvetica,arial,freesans,clean,sans-serif;font-size:15px;line-height:25px;margin:15px 0px\"\u003e\u003cspan style\u003d\"font-size:15px;background-color:transparent\"\u003eRun Chrome with the \"--enable-spdy4\" command-line flag (an internal name for HTTP/2).\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"color:rgb(51,51,51);font-family:Helvetica,arial,freesans,clean,sans-serif;font-size:15px;line-height:25px\"\u003e\u003cp style\u003d\"margin:15px 0px\"\u003eEnjoy!\u003c/p\u003e\u003cp style\u003d\"margin:15px 0px\"\u003eContact \u003ca href\u003d\"mailto:bnc@chromium.org\" style\u003d\"color:rgb(65,131,196);text-decoration:none\"\u003eBence Béky\u003c/a\u003e if you have questions.\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003e\u003cfont color\u003d\"#333333\" face\u003d\"Helvetica, arial, freesans, clean, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15.199999809265137px;line-height:25px\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5048080902362104097"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/spdy/http2"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5831823228453817015"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5831823228453817015"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5831823228453817015"}],"author":[{"name":{"$t":"Fred Akalin"},"email":{"$t":"akalin@chromium.org"}}],"sites$pageName":{"$t":"http2"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/897152553220824044"},"published":{"$t":"2014-09-04T06:30:04.470Z"},"updated":{"$t":"2014-09-04T06:30:04.503Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-04T06:30:04.470Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-09-02 17_21_50.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/897152553220824044"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8249727978514538455"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/setup/Screenshot%20from%202014-09-02%2017_21_50.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/897152553220824044"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/897152553220824044"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/897152553220824044"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/897152553220824044"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1891806941829006262"},"published":{"$t":"2014-09-04T06:29:20.267Z"},"updated":{"$t":"2014-09-04T06:29:20.302Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-04T06:29:20.267Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-09-02 17_21_38.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1891806941829006262"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8249727978514538455"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/setup/Screenshot%20from%202014-09-02%2017_21_38.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1891806941829006262"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1891806941829006262"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1891806941829006262"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1891806941829006262"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3798029156217054251"},"published":{"$t":"2014-09-04T06:17:08.375Z"},"updated":{"$t":"2014-09-04T06:20:08.107Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-04T06:20:08.093Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-09-02 17_21_50.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3798029156217054251"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8018733080906717822"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/releasenotes/Screenshot%20from%202014-09-02%2017_21_50.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3798029156217054251"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3798029156217054251"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3798029156217054251"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3798029156217054251"}],"author":[{}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2017433289987770578"},"published":{"$t":"2014-09-04T06:17:05.642Z"},"updated":{"$t":"2014-09-04T06:20:04.968Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-04T06:20:04.951Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screenshot from 2014-09-02 17_21_38.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2017433289987770578"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8018733080906717822"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/releasenotes/Screenshot%20from%202014-09-02%2017_21_38.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2017433289987770578"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2017433289987770578"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2017433289987770578"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2017433289987770578"}],"author":[{}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"Xil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/346879369230755664"},"published":{"$t":"2013-12-03T18:36:31.466Z"},"updated":{"$t":"2014-09-03T21:49:52.803Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-09-03T21:49:52.791Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Education"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv\u003eSecurity is a core principle and shared responsibility for everyone contributing to Chromium. Here are some docs that can help an engineer get ramped up to Chrome-specific security best practices, pitfalls, or relevant background. Send your c\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eomments, questions, or additional security education needs to security-dev@chromium.org\u003c/span\u003e\u003c/div\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/education/security-tips-for-ipc\" style\u003d\"background-color:transparent;font-size:10pt\"\u003eIPC Security Tips\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e, a thrilling read about how to avoid introducing an IPC vulnerability and feature in the next \u003c/span\u003e\u003ca href\u003d\"http://blog.chromium.org/2012/05/tale-of-two-pwnies-part-1.html\" style\u003d\"background-color:transparent;font-size:10pt\"\u003ePwnium\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e contest.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eSecurity tips for avoiding common vulnerabilities and abuse vectors when \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/education/security-tips-for-crx-and-apps\" style\u003d\"background-color:transparent;font-size:10pt\"\u003edeveloping extensions and apps\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/education/tls\"\u003eEverything you wanted to know about TLS/SSL in Chrome\u003c/a\u003e\u003c/li\u003e\u003cli\u003eIf you are implementing a Chrome Extension/App API, read the \u003ca href\u003d\"https://docs.google.com/document/d/1RamP4-HJ7GAJY3yv2ju2cK50K9GhOsydJN6KIO81das/pub\"\u003esecurity guidelines for Chrome Extension \u0026amp; App API developers\u003c/a\u003e.\u003c/li\u003e\u003cli\u003eDo not implement your own allocator. Custom allocators are a major source of \u003ca href\u003d\"https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId\u003d437\" rel\u003d\"nofollow\"\u003esecurity vulnerabilities\u003c/a\u003e. Chrome's existing allocators (e.g. \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/tcmalloc/chromium/src/\u0026amp;q\u003dtcmalloc\u0026amp;sq\u003dpackage:chromium\"\u003eTcmalloc\u003c/a\u003e, \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/wtf/PartitionAlloc.h\u0026amp;q\u003dPartitionAlloc\u0026amp;sq\u003dpackage:chromium\u0026amp;type\u003dcs\u0026amp;l\u003d1\"\u003ePartitionAlloc\u003c/a\u003e) and resillient to security issues. If you absolutely need to implement some form of custom allocator, make sure to get a thorough review from the security team.\u003c/li\u003e\u003cli\u003eWhen manipulating buffers in trusted memory, do not implement your own code for handling \u003ca href\u003d\"http://en.wikipedia.org/wiki/Integer_overflow#Security_ramifications\" rel\u003d\"nofollow\"\u003einteger overflows\u003c/a\u003e, truncations, or other integral boundary conditions. Instead use \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/base/numerics/\u0026amp;ct\u003drc\u0026amp;cd\u003d1\u0026amp;q\u003dbase/numerics\u0026amp;sq\u003dpackage:chromium\"\u003ebase/numerics\u003c/a\u003e templates which are already used in several parts of Chrome. The following refernces are also good resources on integer security issues:\u003c/li\u003e\u003cul\u003e\u003cli\u003eCERT C++ \u003ca href\u003d\"https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId\u003d637\" rel\u003d\"nofollow\"\u003eSecure Coding Standard\u003c/a\u003e.\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eMark Dowd, John McDonald, Justin Schuh, \u003c/span\u003e\u003ca href\u003d\"http://www.amazon.com/Art-Software-Security-Assessment-Vulnerabilities/dp/0321444426/ref\u003dsr_1_1?s\u003dbooks\u0026amp;ie\u003dUTF8\u0026amp;qid\u003d1402949525\u0026amp;sr\u003d1-1\u0026amp;keywords\u003dThe+Art+of+Software+Security+Assessment\" style\u003d\"font-size:10pt;background-color:transparent\" rel\u003d\"nofollow\"\u003eThe Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eRobert C. Seacord, \u003c/span\u003e\u003ca href\u003d\"http://www.amazon.com/Secure-Coding-Robert-C-Seacord/dp/0321335724\" style\u003d\"font-size:10pt;background-color:transparent\" rel\u003d\"nofollow\"\u003eSecure Coding in C and C++\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6743906577140407009"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/education"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/346879369230755664"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/346879369230755664"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/346879369230755664"}],"author":[{"name":{"$t":"Parisa Tabriz"},"email":{"$t":"parisa@chromium.org"}}],"sites$pageName":{"$t":"education"},"sites$revision":{"$t":"17"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4189676372093792796"},"published":{"$t":"2012-05-02T20:39:05.177Z"},"updated":{"$t":"2014-08-30T16:48:38.977Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-30T16:48:37.794Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"ModemManager care and feeding"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eUpdating modemmanager-next from upstream. ModemManager is an actively-developed project, and we're currently tracking their git master and working with the upstream team on new features. As such, we need to integrate code from upstream with some regularity. \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSetup: Have a repo set up as follows:\u003c/div\u003e\u003cdiv\u003eCheck out upstream:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git clone git://anongit.freedesktop.org/ModemManager/ModemManager\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003eAdd the ChromiumOS repo as a remote:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git remote add chromiumos https://chromium.googlesource.com/chromiumos/third_party/modemmanager-next.git\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis repo can be reused for multiple updates.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eEach time you want to update from upstream:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git fetch\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git co origin/master\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git co -b merge-${DATE} # the branch name is arbitrary, I found this pattern handy\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git fetch chromiumos\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git merge chromiumos/master\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eResolve any conflicts.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTest that the new source compiles and works. (I generally did this by\u003c/div\u003e\u003cdiv\u003emoving aside the src/third-party/modemmanager-next directory and\u003c/div\u003e\u003cdiv\u003emoving this working repository into its place).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTest that dependencies (currently, Shill) compile and work, since\u003c/div\u003e\u003cdiv\u003ethey're sensitive to the MM DBus API.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003ePush to the chromiumos repo (upstream branch and master)\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git push chromiumos origin/master:refs/heads/upstream\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e$ git push chromiumos merge-${DATE}:refs/heads/master\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/modemmanager"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4189676372093792796"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4189676372093792796"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4189676372093792796"}],"author":[{}],"sites$pageName":{"$t":"modemmanager"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6185759639537789873"},"published":{"$t":"2009-11-19T17:03:27.783Z"},"updated":{"$t":"2014-08-29T22:47:00.690Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2011-04-22T00:46:10.155Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Software Architecture"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Abstract\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eAbstract\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-High-level-design\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eHigh-level design\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware-\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eFirmware \u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-System-level-and-user-land-software\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eSystem-level and user-land software\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chromium-and-the-window-manager\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eChromium and the window manager\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Abstract\" /\u003eAbstract\u003c/h2\u003e\r\n\u003cdiv\u003eChromium OS consists of three major components: \u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eThe Chromium-based browser and the window manager\u003c/li\u003e\r\n\u003cli\u003eSystem-level software and user-land services: the kernel, drivers, connection manager, and so on\u003c/li\u003e\r\n\u003cli\u003eFirmware \u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"http://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/software-architecture/overview.png?attredirects\u003d0\" imageanchor\u003d\"1\" rel\u003d\"nofollow\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1258650210340/chromium-os/chromiumos-design-docs/software-architecture/overviewpng\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-High-level-design\" /\u003eHigh-level design\u003c/h2\u003e\r\n\u003cdiv\u003eWe'll look at each component, starting with the firmware.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Firmware-\" /\u003eFirmware \u003c/h3\u003e\r\n\u003cdiv\u003eThe firmware plays a key part to make booting the OS faster and more secure. To achieve this goal we are removing unnecessary components and adding support for verifying each step in the boot process. We are also adding support for system recovery into the firmware itself. We can avoid the complexity that's in most PC firmware because we don't have to be backwards compatible with a large amount of legacy hardware. For example, we don't have to probe for floppy drives.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eOur firmware will implement the following functionality:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery\"\u003e\u003cb\u003eSystem recovery\u003c/b\u003e\u003c/a\u003e\u003cb\u003e:\u003c/b\u003e The recovery firmware can re-install Chromium OS in the event that the system has become corrupt or compromised.\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;border-collapse:collapse\"\u003e\u003cb\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified boot\u003c/a\u003e:\u003c/b\u003e  Each time the system boots, Chromium OS verifies that the firmware, kernel, and system image have not been tampered with or become corrupt. This process starts in the firmware.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery\"\u003e\u003cb\u003eFast boot\u003c/b\u003e\u003c/a\u003e\u003cb\u003e:\u003c/b\u003e We have improved boot performance by removing a lot of complexity that is normally found in PC firmware.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"http://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/software-architecture/firmware.png?attredirects\u003d0\" imageanchor\u003d\"1\" rel\u003d\"nofollow\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1258650211434/chromium-os/chromiumos-design-docs/software-architecture/firmwarepng\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-System-level-and-user-land-software\" /\u003eSystem-level and user-land software\u003c/h3\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003eFrom here we bring in the Linux kernel, drivers, and user-land daemons. Our kernel is mostly stock except for a handful of patches that we pull in to improve boot performance. On the user-land side of things we have streamlined the init process so that we're only running services that are critical. All of the user-land services are managed by Upstart. By using Upstart we are able to start services in parallel, re-spawn jobs that crash, and defer services to make boot faster. \u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003eHere's a quick list of things that we depend on:\u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003eD-Bus:\u003c/b\u003e The browser uses D-Bus to interact with the rest of the system. Examples of this include the battery meter and network picker. \u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eConnection Manager:\u003c/b\u003e Provides a common API for interacting with the network devices, provides a DNS proxy, and manages network services for 3G, wireless, and ethernet.  \u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eWPA Supplicant:\u003c/b\u003e Used to connect to wireless networks.\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eAutoupdate:\u003c/b\u003e Our autoupdate daemon silently installs new system images. \u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003ePower Management:\u003c/b\u003e (ACPI on Intel) Handles power management events like closing the lid or pushing the power button. \u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003eStandard Linux services:\u003c/b\u003e NTP, syslog, and cron.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Chromium-and-the-window-manager\" /\u003eChromium and the window manager\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eThe window manager is responsible for handling the user's interaction with multiple client windows. It does this in a manner similar to that of other X window managers, by controlling window placement, assigning the input focus, and exposing hotkeys that exist outside the scope of a single browser window. Parts of the ICCCM (Inter-Client Communication Conventions Manual) and EWHM (Extended Window Manager Hints) specifications are used for communication between clients and the window manager where possible.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThe window manager also uses the XComposite extension to redirect client windows to offscreen pixmaps so that it can draw a final, composited image incorporating their contents itself. This lets windows be transformed and blended together. The window manager contains a compositor that animates these windows and renders them via OpenGL or OpenGL|ES.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"http://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/software-architecture/chrome.png?attredirects\u003d0\" imageanchor\u003d\"1\" rel\u003d\"nofollow\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1258650212610/chromium-os/chromiumos-design-docs/software-architecture/chromepng\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/software-architecture"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6185759639537789873"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6185759639537789873"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6185759639537789873"}],"author":[{}],"sites$pageName":{"$t":"software-architecture"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},"published":{"$t":"2014-08-28T10:05:37.979Z"},"updated":{"$t":"2014-08-28T15:23:57.584Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T13:09:37.286Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Complex policies on Windows"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Background\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eBackground\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-New-in-Chrome-37:-complex-policies\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eNew in Chrome 37: complex policies\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-JSON-values-as-strings\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eJSON values as strings\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Option-1:-JSON-strings-in-the-GPO-editor\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eOption 1: JSON strings in the GPO editor\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Option-2:-JSON-strings-in-the-registry-editor\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eOption 2: JSON strings in the registry editor\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Option-3:-expanded-JSON-in-the-registry\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eOption 3: expanded JSON in the registry\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Troubleshooting\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eTroubleshooting\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Background\" /\u003eBackground\u003c/h2\u003e\u003cdiv\u003eChrome represents policies as JSON values internally. Up until version 37 all Chrome policies were of simple types:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cb\u003eBooleans\u003c/b\u003e (example: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/policy-list-3#SafeBrowsingEnabled\"\u003eSafeBrowsingEnabled\u003c/a\u003e)\u003c/li\u003e\u003cli\u003e\u003cb\u003eIntegers\u003c/b\u003e (example: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/policy-list-3#DefaultCookiesSetting\"\u003eDefaultCookiesSetting\u003c/a\u003e)\u003c/li\u003e\u003cli\u003e\u003cb\u003eStrings\u003c/b\u003e (example: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/policy-list-3#ProxyPacUrl\"\u003eProxyPacUrl\u003c/a\u003e)\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003eAdditionally, Chrome has supported some policies as \u003cb\u003eLists of Strings\u003c/b\u003e (example: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/policy-list-3#URLBlacklist\"\u003eURLBlacklist\u003c/a\u003e).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThese policy types match what GPO can represent natively on Windows using Administrative Template files (ADM or ADMX).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSome policies need more complex values that don't fit well in any of these types. For example, \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/policy-list-3#ExtensionInstallForcelist\"\u003eExtensionInstallForcelist\u003c/a\u003e defines a list of extensions to install automatically. Each extension is defined by its extension ID and a remote update URL (to support extensions from private stores). This can be easily represented in JSON as a list of objects, where each object has two strings:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-color:rgb(136,136,136);border-width:1px\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"width:551px;height:58px\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[\u003cbr /\u003e  {\u003cbr /\u003e    \"id\": \"public-ext-id-1\",\u003cbr /\u003e    \"update_url\": \"https://clients2.google.com/service/update2/crx\"\u003cbr /\u003e  },\u003cbr /\u003e  {\u003cbr /\u003e    \"id\": \"private-ext-id-2\",\u003cbr /\u003e    \"update_url\": \"http://www.local/chrome/updates.xml\"\u003cbr /\u003e  }\u003cbr /\u003e]\u003cbr /\u003e\u003c/font\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eUnfortunately there is no native GPO type to represent this and the policy needs to be configured as a List of Strings, where each string contains both the ID and the update URL separated by a semicolon:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-color:rgb(136,136,136);border-width:1px\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd style\u003d\"width:547px;height:64px\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[\u003cbr /\u003e  \"public-ext-id-1;\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003ehttps://clients2.google.com/service/update2/crx\",\u003cbr /\u003e\u003c/span\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \"private-ext-id-2;\u003c/font\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003ehttp://www.local/chrome/updates.xml\"\u003cbr /\u003e\u003c/span\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e]\u003c/font\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-New-in-Chrome-37:-complex-policies\" /\u003eNew in Chrome 37: complex policies\u003c/h2\u003e\u003cdiv\u003eChrome 37 introduced new policies with complex values that don't fit in any of the native GPO or Registry types: \u003ca href\u003d\"http://www.chromium.org/administrators/policy-list-3#RegisteredProtocolHandlers\"\u003eRegisteredProtocolHandlers\u003c/a\u003e and \u003ca href\u003d\"http://www.chromium.org/administrators/policy-list-3#ManagedBookmarks\"\u003eManaged Bookmarks\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThere are 3 ways to configure the values for these policies: as a JSON string in the GPO editor, as a JSON string in the registry, or as an expanded JSON object in the registry.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-JSON-values-as-strings\" /\u003eJSON values as strings\u003c/h2\u003e\u003cdiv\u003eAll of these policies can be configured as strings that contain a JSON value. Any JSON editor should able to edit and validate the JSON string, including some \u003ca href\u003d\"http://google.com/search?q\u003djson%20editor\"\u003eonline editors\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eJSON can contain simple values:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eStrings are wrapped in quotes: \u003cfont face\u003d\"courier new, monospace\"\u003e\"example string value\"\u003c/font\u003e\u003c/li\u003e\u003cli\u003eIntegers are just spelled out: \u003cfont face\u003d\"courier new, monospace\"\u003e123\u003c/font\u003e\u003c/li\u003e\u003cli\u003eBoolean values can be specified as \u003cfont face\u003d\"courier new, monospace\"\u003etrue\u003c/font\u003e or \u003cfont face\u003d\"courier new, monospace\"\u003efalse\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eJSON supports lists of values. The values should be enclosed between \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e and \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e]\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e and separated by commas:\u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e [ \"this\", \"is\", \"a\", \"list\", \"of\", \"strings\" ]\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e.\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eJSON also supports objects (sometimes called dictionaries), which contain a string key mapped to any other valid JSON value (which may be a list or another object/dictionary): \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e{ \"key\": \"string value\", \"key that maps to integer\": 123, \"key that maps to list\": [ 1, 2, 3 ] }\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThe examples below will configure the \u003ca href\u003d\"http://www.chromium.org/administrators/policy-list-3#ManagedBookmarks\"\u003eManaged Bookmarks\u003c/a\u003e policy to build this bookmark structure:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eGoogle (google.com)\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eYouTube (youtube.com)\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eChrome links\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eChromium (chromium.org)\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eList of Policies (http://www.chromium.org/administrators/policy-list-3)\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eEach bookmark is a JSON object with a \"name\" key indicating its name, and a \"url\" key indicating the URL or a \"children\" key that maps to another list of bookmarks, to create folders.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThe JSON string for the structure listed above is:\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e[ { \"name\": \"Google\", \"url\": \"google.com\" }, { \"name\": \"YouTube\", \"url\": \"youtube.com\" }, { \"name\": \"Chrome links\", \"children\": [ { \"name\": \"Chromium\", \"url\": \"chromium.org\" }, { \"name\": \"List of Policies\", \"url\": \"\u003cspan style\u003d\"background-color:transparent\"\u003ehttp://www.chromium.org/administrators/policy-list-3\" } ] } ]\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/bookmarks4.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409227455744/administrators/complex-policies-on-windows/bookmarks4.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Option-1:-JSON-strings-in-the-GPO-editor\" /\u003eOption 1: JSON strings in the GPO editor\u003c/h2\u003e\u003cdiv\u003eIf you use the ADM or ADMX templates you can just locate the policy to configure (in this case, \"Managed Bookmarks\"), enable it, and set the JSON string in the string field for that policy:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/bookmarks5.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409227745026/administrators/complex-policies-on-windows/bookmarks5.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Option-2:-JSON-strings-in-the-registry-editor\" /\u003eOption 2: JSON strings in the registry editor\u003c/h2\u003e\u003cdiv\u003e\u003cb\u003eNote\u003c/b\u003e: Chrome only loads policies directly from the registry on AD enrolled machines.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eChrome policies can be configured under Software\\Policies\\Google\\Chrome (or Software\\Policies\\Chromium for Chromium) in HKCU or HKLM. For complex policies, just create a new String value with the policy name and set the JSON string in the Value field.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/bookmarks6.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409227969763/administrators/complex-policies-on-windows/bookmarks6.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Option-3:-expanded-JSON-in-the-registry\" /\u003eOption 3: expanded JSON in the registry\u003c/h2\u003e\u003cdiv\u003e\u003cb\u003eNote\u003c/b\u003e: Chrome only loads policies directly from the registry on AD enrolled machines.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eChrome will try to load JSON lists and JSON objects/dictionaries directly from the registry too, for the new complex policies. This format makes it easier to directly edit the policy values in the registry but requires understanding how a JSON list and a JSON dictionary can be represented in the registry.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe basic rules are:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eStrings are stored as String Values (right-click on the right side, choose New -\u0026gt; String Value)\u003c/li\u003e\u003cli\u003eIntegers are stored as Dword Values (New -\u0026gt; DWORD (32-bits))\u003c/li\u003e\u003cli\u003eBooleans are also stored as Dword Values. Use 0 for false and 1 for true.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eObjects/dictionaries can contain any of these simple types. Just add the value as described above, and use the \"Value Name\" field to set the name of the entry in the dictionary.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf the entry in the dictionary is a list or another dictionary then you can create a new Key on the left side of the registry editor. Its name will be used for the dictionary key name, and its contents will be interpreted as another dictionary.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eLists are represented just like dictionaries, but they key names must be \"1\", \"2\", \"3\" and so on. Note that counting starts at 1 and not at 0 (this is what the GPO editor does for lists too). Chrome knows the expected policy format internally, and will load each entry as a list or object as appropriate.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eHere's an example for the Managed Bookmarks configuration listed above. Start by creating a new registry Key (these are shown as folders on the left side) named \"ManagedBookmarks\":\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg1.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409228921754/administrators/complex-policies-on-windows/reg1.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003eThe value of this policy is a list of objects, so this folder will contain other subfolders named \"1\", \"2\", etc. Start by creating a subfolder named \"1\":\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg2.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409228925748/administrators/complex-policies-on-windows/reg2.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003eThe contents of this folder are the keys for the first object inside the list of bookmarks. You can now add the 2 strings that declare a bookmark, the \"name\" and the \"url\". This configuration should be enough to show one bookmark in Chrome.\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003eTo add bookmark folders, start by adding a new entry in the main list (see folder \"3\" below) and give the folder a \"name\" too. But instead of specifying a \"url\", add a new subfolder named \"children\" that contains the bookmarks for that folder. The \"children\" folder is a list of bookmarks, so it should contain subfolders named \"1\", \"2\", etc again.\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg3.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409228928995/administrators/complex-policies-on-windows/reg3.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003eEach child bookmark of the folder needs to have its \"name\" and \"url\" defined again:\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg4.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1409228930928/administrators/complex-policies-on-windows/reg4.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2 style\u003d\"display:block;text-align:left\"\u003e\u003ca name\u003d\"TOC-Troubleshooting\" /\u003eTroubleshooting\u003c/h2\u003e\u003cdiv\u003eThe first step to diagnose problems is the internal chrome://policy page. You should see your policies listed in that page and their corresponding values.\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eIf the policy is present and its value is shown too but it doesn't seem to work then this might be a new bug. Please file a new report at \u003ca href\u003d\"http://crbug.com\"\u003ecrbug.com\u003c/a\u003e with the Enterprise template.\u003c/li\u003e\u003cli\u003eIf the policy is present but the value is invalid then there is a problem in the JSON configuration.\u003c/li\u003e\u003cli\u003eIf the policy is not present then it wasn't found by Chrome.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ePolicies configured via GPO have some delay until they are applied; run the \u003cfont face\u003d\"courier new, monospace\"\u003egpupdate\u003c/font\u003e command to flush them. If you use the registry then note that Chrome only loads those policies on machines that are enrolled to an AD domain.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIt's generally a good idea to validate your JSON string to make sure it doesn't have any invalid constructs; a common source of errors is trailing commas at the end of a list or a dictionary, which is not supported in JSON. Use an \u003ca href\u003d\"http://google.com/search?q\u003djson%20validator\"\u003eonline JSON validator\u003c/a\u003e (like \u003ca href\u003d\"http://jsonlint.com/\" rel\u003d\"nofollow\"\u003eJSONLint\u003c/a\u003e) to make sure your JSON string is valid.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7817060016656641064"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6755979336652082647"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$pageName":{"$t":"complex-policies-on-windows"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7897944442324178970"},"published":{"$t":"2014-08-20T19:57:51.452Z"},"updated":{"$t":"2014-08-28T15:07:09.253Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T15:07:06.844Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Developer Guide: Certificate Management Extension API on Chrome OS"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"text-align:justify;font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis document is for extension developers and describes how to use the extension API \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys\" style\u003d\"line-height:1.15;text-align:justify;font-size:10pt;text-decoration:none;background-color:transparent\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"text-align:justify;font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e for client certificate enrollment.\u003c/span\u003e\u003c/p\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt;text-align:justify\"\u003e\u003ca name\u003d\"TOC-Motivation\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Trebuchet MS;font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMotivation\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eClient certificates allow secure authentication to digital resources, like networks or web resources. A typical certificate based authentication protocol is \u003c/span\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Transport_Layer_Security\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(11,0,128);vertical-align:baseline;white-space:pre-wrap\"\u003eTransport Layer Security\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e (TLS, formerly known as SSL) and the protocols that are built on top like EAP-TLS for network authentication and HTTPS for web resources.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis article describes how to manage and make use of client certificates on Chrome OS using the \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e extension API: in particular, how to provision a new client certificate and how to use a client certificate for network or web authentication.\u003c/span\u003e\u003c/p\u003e\u003ch2 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt;text-align:justify\"\u003e\u003ca name\u003d\"TOC-Overview\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Trebuchet MS;font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eOverview\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMany certificate enrollment protocols exist, like \u003c/span\u003e\u003ca href\u003d\"http://tools.ietf.org/html/draft-nourse-scep-23\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSCEP\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, \u003c/span\u003e\u003ca href\u003d\"https://tools.ietf.org/html/rfc7030\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eEST\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e or \u003c/span\u003e\u003ca href\u003d\"https://tools.ietf.org/html/rfc5272\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCMC\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, that define the communication between the client (in this case, the Chrome OS device) and the Certificate Authority (CA), which can be accompanied by a Registration Authority. The \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e API is designed in a way that extensions have the freedom to implement any enrollment protocol based on what is supported by the target Certificate Authority.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIndependent of which specific protocol is used to communicate, the following steps describe the typical flow of a certificate enrollment:\u003c/span\u003e\u003c/p\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eTrigger the enrollment process, e.g. the user tries to authenticate but no client cert is installed, or the user manually starts the enrollment.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eObtain the enrollment configuration, e.g. URL of the CA, or the attributes to use for the certification request.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eObtain credentials to authenticate the certification request, either by asking the user or by using an API, e.g. \u003ca href\u003d\"https://developer.chrome.com/apps/identity\" target\u003d\"_blank\"\u003echrome.identity\u003c/a\u003e.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eGenerate public/private key pair locally on the device.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eCreate the certification request, which contains data like the public key and some attributes, which in turn is signed by the private key. The private key is kept secret and is not part of the request.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSend the certification request to the CA.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAfter the CA authorizes the request, it creates the client certificate and sends it to the client.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe client receives the certificate and installs it.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAfter successful enrollment the certificate can be used to authenticate to resources like a network or a web page.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt;text-align:justify\"\u003e\u003ca name\u003d\"TOC-The-enterprise.platformKeys-API\" /\u003e\u003cspan style\u003d\"font-size:21px;font-family:Trebuchet MS;font-weight:normal;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe enterprise.platformKeys API\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis extension API of Chrome OS allows extensions to generate a key pair, sign a certification request, and to manage the installed client certificates (import, get and remove certificates). Using this API, an extension can drive the process of installing a new client certificate to a Chrome OS device.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIn order to use the API, an extension must be pre-installed by user policy. Only extensions installed by policy can use the API.\u003c/span\u003e\u003c/p\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt;text-align:justify\"\u003e\u003ca name\u003d\"TOC-How-to-implement-the-enrollment-process-in-an-extension\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHow to implement the enrollment process in an extension\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e1. The enrollment can be started by several events.\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe extension can expose a link or an icon that the user can use to manually start the enrollment process, see for example \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/browserAction\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003echrome.browserAction\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe first time the user tries to connect to a network that requires a client certificate for authentication, Chrome OS can automatically open the extension if the following required step has been taken by the administrator:\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe network must be configured by policy to use client certificates for authentication (e.g. a 802.1x WiFi with EAP-TLS) and the Client Enrollment URL must be set to a page of the extension, see \u003c/span\u003e\u003ca href\u003d\"https://support.google.com/chrome/a/answer/2634553\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eManage Networks\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eEvery time the user attempts to connect to this network and there is no matching certificate in the user’s certificate store, Chrome OS will open the configured Client Enrollment URL in a new browser tab.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe extension can use an \u003ca href\u003d\"https://developer.chrome.com/extensions/event_pages\"\u003eevent page\u003c/a\u003e (succeeding \u003c/span\u003e\u003cspan style\u003d\"text-decoration:underline;color:rgb(17,85,204);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/background_pages\" style\u003d\"text-decoration:none\"\u003ebackground page\u003c/a\u003e)\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e to check whether a valid client certificate is already installed at certain times (e.g. after login and once per day). If not or if the certificate is expiring soon, the extension can trigger the enrollment flow.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e2. The extension needs some configuration about the enrollment process, at a minimum the URL of the CA and maybe attributes to embed in the certification request.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe configuration can\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ebe part of the extension itself, which prevents reuse of the extension with other configurations,\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ebe part of the Client Enrollment URL that is opened by Chrome OS (see previous step),\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ebe pushed through \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/manifest/storage\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003epolicy for extensions\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, which allows the administrator to configure the extension in the management console.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e3. To obtain credentials to authenticate the certification request at the CA, the extension can present any UI and ask the user to provide the credentials or use any other APIs, for example, OAuth.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e4. The extension has to obtain the user \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#type-Token\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eToken\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e (with the id \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,136,0);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e\"user\"\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e) using \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#method-getTokens\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys.getTokens\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e and generate a key pair using the \u003c/span\u003e\u003ca href\u003d\"http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esubtleCrypto.generateKey\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e method of the \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#type-Token\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eToken\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. The private key will be generated by the TPM and is guaranteed to never leave the device or even the TPM.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003efunction getUserToken(callback) {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e chrome.enterprise.platformKeys.getTokens(function(tokens) {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e   for (var i \u003d 0; i \u0026lt; tokens.length; i++) {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e   if (tokens[i].id \u003d\u003d \"user\") {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e        callback(tokens[i]);\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e        return;\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e      }\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    }\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    callback(null);\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  });\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003evar algorithm \u003d {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  name: \"RSASSA-PKCS1-v1_5\",\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  // RsaHashedKeyGenParams:\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  modulusLength: 2048,\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003e  // Equivalent to 65537\u003c/span\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  publicExponent:\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e new Uint8Array([0x01, 0x00, 0x01]), \u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  hash: {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    name: \"SHA-1\"\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  }\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e};\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003euserToken.subtleCrypto.generateKey(algorithm, false /* not extractable */, [\"sign\"])\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  .then(function(keyPair) { ... continue with generated keyPair ... },\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e        console.error.bind(console));\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e5. Extract the public key from the key handle using the \u003c/span\u003e\u003ca href\u003d\"http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esubtleCrypto.exportKey\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e method of the \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#type-Token\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eToken\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003euserToken.subtleCrypto.exportKey(\"spki\", keyPair.publicKey)\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  .then(function(publicKey) { ... continue with publicKey ... },\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e        console.error.bind(console));\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e6. Create the content for the certification request in the extension. This request must contain at least the public key. The CA may expect additional attributes that must be added. If the request is PKCS#10 based, for example, the open source library \u003c/span\u003e\u003ca href\u003d\"https://github.com/digitalbazaar/forge\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eforge\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e may be used.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003evar request \u003d CreateCertificationRequest();\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003erequest.setPublicKey(publicKey);\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003erequest.setSubject('CommonName', 'some name');\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e7. Sign the content of the certification request (using the \u003c/span\u003e\u003ca href\u003d\"http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003esubtleCrypto.sign\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e method of the \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#type-Token\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eToken\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e) and create the final request from the content and the signature. Any subsequent attempt to use the same key for signing will fail for security reasons: This API guarantees that only Chrome OS itself can use the private key and the certificate for authentication.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003efunction signData(data, callback) {\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  userToken.subtleCrypto.sign({name : \"RSASSA-PKCS1-v1_5\"}, keyPair.privateKey, data)\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    .then(callback, console.error.bind(console));\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003erequest.setSignFunction(signData);\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003erequest.sign();\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e8. Send the certification request to the CA and receive the client certificate (e.g. using XMLHttpRequest)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003evar xhr \u003d new XMLHttpRequest();\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003efunction onReadyStateChange() {\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  if (xhr.readyState !\u003d\u003d 4)\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    return;\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  if (xhr.status !\u003d\u003d 200) {\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-size:15px;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003cfont face\u003d\"monospace\"\u003e\u003ccode\u003e ... h\u003c/code\u003e\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:Arial;font-size:15px;white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003e\u003ccode\u003eandle error ...\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    return;\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  }\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  ... continue with xhr.response which contains the certificate ....\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003exhr.onreadystatechange \u003d onReadyStateChange;\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003exhr.open('POST', caUrl);\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003exhr.setRequestHeader('Content-Type', ...);\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003exhr.send(request);\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e9. Install the client certificate using \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#method-importCertificate\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys.importCertificate\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e   \u003c/span\u003e\u003c/p\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003echrome.enterprise.platformKeys.importCertificate(userToken.id, certificate);\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"white-space:pre-wrap;line-height:1.15;text-align:justify;font-family:Arial;font-size:15px;background-color:transparent\"\u003e10. Different methods to use the client certificate for authentication are available\u003c/span\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor network authentication:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe user can manually select the client certificate in the network configuration dialog.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe selection can also be automated if the network is configured by policy. For network types that support client certificates, like EAP-TLS, the administrator can configure a Certificate Pattern that defines which client certificates are valid for authenticating to this network. Chrome OS will automatically select the most recent matching client certificate and use it for authentication on every connection attempt.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor web pages requiring client certificate authentication:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWhen accessing a web page that requires the client to present a certificate, Chrome OS will show the user a list of available client certificates. After selecting one, Chrome OS will use it to authenticate.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe selection can also be automated for specific URLs using the policy \u003c/span\u003e\u003ca href\u003d\"https://support.google.com/chrome/a/answer/2657289?#AutoSelectCertificateForUrls\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAutomatically select client certificates for these sites\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e:\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eFor URLs that are listed in this policy, the most recent matching client certificate will automatically be used for authentication without prompting the user.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv style\u003d\"text-align:justify\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;line-height:17.25px;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNote that the \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e API guarantees, that client certificates imported using the API can only be used by Chrome OS itself for authentication. The extension is not able to drive any authentication with such a certificate and in particular the API guarantees that the certificate can’t be extracted to authenticate any other user or device.\u003c/span\u003e\u003c/p\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Re-enrollment\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eRe-enrollment\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eTo determine whether any valid client certificate is already installed and to check the expiration of the installed certificates, an extension can use the \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#method-getCertificates\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eplatformKeys.getCertificates\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e function and if necessary trigger the process to obtain a new client certificate.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003echrome.enterprise.platformKeys.getCertificates(userToken.id, function(certificates) {\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  for (var i \u003d 0; i \u0026lt; certificates.length; i++) {\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    var certificate \u003d certificates[i];\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e    ... check whether certificate is valid and matches the required attributes ...\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e  }\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003ccode\u003e});\u003c/code\u003e\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:justify\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAn installed certificate can be removed from the user’s certificate store using the function \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/enterprise_platformKeys#method-removeCertificate\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eenterprise.platformKeys.removeCertificate\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. As client certificates can be selected automatically (see last step in the enrollment process above), unnecessary certificates should be removed to prevent conflicts.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7817060016656641064"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/administrators/certificate-management-extension-api-on-chrome-os"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7897944442324178970"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7897944442324178970"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7897944442324178970"}],"author":[{"name":{"$t":"Philipp Neubeck"},"email":{"$t":"pneubeck@chromium.org"}}],"sites$pageName":{"$t":"certificate-management-extension-api-on-chrome-os"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7272463536229640978"},"published":{"$t":"2014-08-28T12:28:50.897Z"},"updated":{"$t":"2014-08-28T12:28:50.928Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:28:50.897Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"reg4.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7272463536229640978"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg4.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7272463536229640978"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7272463536229640978"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7272463536229640978"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7272463536229640978"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7859737301107374815"},"published":{"$t":"2014-08-28T12:28:48.968Z"},"updated":{"$t":"2014-08-28T12:28:48.995Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:28:48.968Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"reg3.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7859737301107374815"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg3.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7859737301107374815"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7859737301107374815"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7859737301107374815"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7859737301107374815"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8474612684617325368"},"published":{"$t":"2014-08-28T12:28:45.721Z"},"updated":{"$t":"2014-08-28T12:28:45.748Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:28:45.721Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"reg2.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8474612684617325368"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg2.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8474612684617325368"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8474612684617325368"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8474612684617325368"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8474612684617325368"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/319781830949025525"},"published":{"$t":"2014-08-28T12:28:41.729Z"},"updated":{"$t":"2014-08-28T12:28:41.754Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:28:41.729Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"reg1.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/319781830949025525"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/reg1.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/319781830949025525"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/319781830949025525"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/319781830949025525"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/319781830949025525"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6961763510336577439"},"published":{"$t":"2014-08-28T12:12:49.733Z"},"updated":{"$t":"2014-08-28T12:12:49.763Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:12:49.733Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"bookmarks6.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6961763510336577439"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/bookmarks6.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6961763510336577439"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6961763510336577439"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6961763510336577439"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6961763510336577439"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4408209635601248381"},"published":{"$t":"2014-08-28T12:09:04.997Z"},"updated":{"$t":"2014-08-28T12:09:05.026Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:09:04.997Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"bookmarks5.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4408209635601248381"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/bookmarks5.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4408209635601248381"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4408209635601248381"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4408209635601248381"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4408209635601248381"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7782531430287036376"},"published":{"$t":"2014-08-28T12:04:15.710Z"},"updated":{"$t":"2014-08-28T12:04:15.744Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-28T12:04:15.710Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"bookmarks4.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7782531430287036376"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6755979336652082647"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/complex-policies-on-windows/bookmarks4.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7782531430287036376"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7782531430287036376"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7782531430287036376"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7782531430287036376"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7134831505460377985"},"published":{"$t":"2014-08-26T23:37:20.249Z"},"updated":{"$t":"2014-08-26T23:37:20.249Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-26T23:37:20.249Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7134831505460377985"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7134831505460377985"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7134831505460377985"}],"author":[{"name":{"$t":"Ryan Hamilton"},"email":{"$t":"rch@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/document/d/1pHtodNt3Bk0YliLTPmq42LaZaKGcD_v-ZqDtrJFxXzc/edit?usp\u003dsharing\"\u003eSPDY/QUIC Connection Pooling Bug Postmortem\u003c/a\u003e"},{"index":"B","name":"Date","$t":""}]},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/613112853590456588"},"published":{"$t":"2014-08-25T17:32:13.525Z"},"updated":{"$t":"2014-08-25T17:32:38.231Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-25T17:32:38.231Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/613112853590456588"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/613112853590456588"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/613112853590456588"}],"author":[{"name":{"$t":"James Cook"},"email":{"$t":"jamescook@chromium.org"}}],"sites$revision":{"$t":"2"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/a/chromium.org/document/d/1wkxPKzWt3Xb3tjczhHl66Y5uCgO0EeE5mlDd9xIHbiE/edit\"\u003ePostmortem: 15 hour tree closure by a file named \"about\"\u003c/a\u003e"},{"index":"B","name":"Date","$t":"2014-05-09"}]},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6557445848164381896"},"published":{"$t":"2014-08-25T15:28:04.156Z"},"updated":{"$t":"2014-08-25T16:04:22.346Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-25T16:04:20.606Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Handle file upload scheme"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003eSome client application need to handle the actual upload of the crash reports, specially on Mac or iOS where using NSUrlSession is mandatory on some conditions.. It can be done by adding support of the file:// scheme for upload URL. \u003c/font\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:2pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThree main modifications have to be done to breakpad to support this feature.\u003c/span\u003e\u003c/p\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:2pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWrite the HTTP request to file.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:2pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBreakpad thread.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:2pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSeparate the request creation and the response handler.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:2pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eAs Breakpad is used by multiple applications on multiple platforms, the standard behavior has to be preserved if the scheme is not file://.\u003c/span\u003e\u003c/p\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Write-the-HTTP-request-to-file\" /\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eWrite the HTTP request to file\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"white-space:pre-wrap;line-height:1.15;background-color:transparent\"\u003eIt is possible to set the uploading URL in the config NSDictionary* to a temporary file://. This requires an API to get the configuration dictionary. This URL can then be checked in the HTTPMultipartUpload send method, and in case of a file:// scheme, the request is written in a file.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Breakpad-thread.\" /\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBreakpad thread.\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eEvery call in Breakpad must be executed in the breakpad thread. This implies to use the [BreakpadController withBreakpadRef:] method that will ensure that operations are executed in the correct thread.\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Separate-the-request-creation-and-the-response-handler.\" /\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSeparate the request creation and the response handler.\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe biggest change in the project is the separation of the request creation and the response handler. It is possible for the client to wait a long time before sending the report. The two phases send the report and interpret the response have to be splitted.\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"vertical-align:baseline;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eBreakpad renames the minidump from the minidumpID to an ID contained in the HTTP response. At the moment the response is received, it is necessary to have both IDs. An API has to be provided to the client to store the configuration NSDictionary, and to reconstruct the upload objects using it.\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"vertical-align:baseline;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"vertical-align:baseline;background-color:transparent\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cb\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003eProposed new API :\u003c/font\u003e\u003c/b\u003e\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-HTTPMultipartUpload:\" /\u003e\u003cspan style\u003d\"color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eHTTPMultipartUpload:\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- [HTTPMultipartUpload send] : (modified)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis method will test if the url scheme is file://. In that case, the request body is written to the pointed file and method returns nil.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Uploader\" /\u003e\u003cspan style\u003d\"color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eUploader\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- [Uploader report] (modified)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eSplit this method into two method :\u003c/span\u003e\u003c/p\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- [Uploader report] that will initiate the upload\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;vertical-align:baseline;background-color:transparent\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- [handleResponse:(NSData*)response withError:(NSError*)error] that will handle the response.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eIf the URL is not file://, - [Uploader report] will directly call - [handleResponse:(NSData*)response withError:(NSError*)error].\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- [handleResponse:(NSData*)response withError:(NSError*)error] (added)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003ethat will handle the response.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNSDictionary *readConfigurationData(const char *configFile); (added)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe configuration has to be saved to be able to recreate the uploader object when the network response is received. This method has to be public.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Breakpad\" /\u003e\u003cspan style\u003d\"color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBreakpad\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eNSDictionary* BreakpadGetNextReportConfiguration(BreakpadRef ref); (added)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis method is needed to retrieve the configuration of the next report to be uploaded.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003evoid BreakpadUploadReportWithParametersAndConfiguration(BreakpadRef ref,\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e                                                          NSDictionary *server_parameters,\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e                                                        NSDictionary *configuration); (added)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003evoid BreakpadHandleNetworkResponse(BreakpadRef ref,\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e                                   NSDictionary* configuration,\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e                                   NSData* data,\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e                                   NSError* error); (added)\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-BreakpadController-:\" /\u003e\u003cspan style\u003d\"color:rgb(102,102,102);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eBreakpadController :\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e- (void)threadUnsafeSendReportWithConfiguration:(NSDictionary*)configuration\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;margin-left:144pt\"\u003e\u003cspan style\u003d\"color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e     withBreakpadRef:ref; (added)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThis method calls BreakpadUploadReportWithParametersAndConfiguration in the current thread. It is needed to keep the sequentiality of the operations. As the name of the method suggests, it is threadUnsafe and should only be used from the - (void)withBreakpadRef:(void(^)(BreakpadRef))callback\u003c/span\u003e\u003c/p\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e callback.\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"3\"\u003e \u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3346586720904756379"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/crash-reports/handle-file-upload-scheme"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6557445848164381896"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6557445848164381896"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6557445848164381896"}],"author":[{"name":{"$t":"Olivier Robin"},"email":{"$t":"olivierrobin@chromium.org"}}],"sites$pageName":{"$t":"handle-file-upload-scheme"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5314001004053513006"},"published":{"$t":"2014-08-22T18:26:43.624Z"},"updated":{"$t":"2014-08-22T18:26:43.624Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-22T18:26:43.624Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4358412840446130955"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5314001004053513006"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5314001004053513006"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5314001004053513006"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Title","$t":"\u003ca xmlns\u003d\"http://www.w3.org/1999/xhtml\" href\u003d\"https://docs.google.com/a/chromium.org/document/d/1O2CUqFGMJ6uHP_hBdh9i9AHIOY96nTYaKRa6c4oAHJs/edit#heading\u003dh.cg9oxhygkrer\"\u003eGrit Compile Errors Require Clobber\u003c/a\u003e"},{"index":"B","name":"Date","$t":"2014-07-25"}]},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7228587109453827465"},"published":{"$t":"2014-08-15T23:38:53.071Z"},"updated":{"$t":"2014-08-15T23:38:53.096Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-15T23:38:53.071Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromeos_touch_accessibility_user_flow.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7228587109453827465"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/583855195809576726"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/user-experience/touch-access/chromeos_touch_accessibility_user_flow.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7228587109453827465"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7228587109453827465"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7228587109453827465"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7228587109453827465"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8508306572198298395"},"published":{"$t":"2014-08-14T16:40:53.034Z"},"updated":{"$t":"2014-08-14T16:40:53.074Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-14T16:40:53.034Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"playing_around (2).png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8508306572198298395"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/583855195809576726"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/user-experience/touch-access/playing_around%20(2).png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8508306572198298395"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8508306572198298395"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8508306572198298395"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8508306572198298395"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7393313184595945406"},"published":{"$t":"2014-07-17T16:55:10.765Z"},"updated":{"$t":"2014-08-11T23:43:16.928Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-08-11T23:41:28.027Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Analyze step(s)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eThe analyze step is used to determine if a compile is necessary for the current platform and if a compile is necessary the set of targets (tests) to execute. By default all try bots run the analyze step. To make a bot not run the analyze step add the name of the bot to the non_filter_builders key (non_filter_builders is expected to be an array of strings) in the corresponding trybot file. For example, to opt out the trybot win_chromium_rel_swarming add win_chromium_rel_swarming to the key non_filter_builders in the file \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/testing/buildbot/chromium_trybot.json\" style\u003d\"font-size:10pt;background-color:transparent\"\u003echromium_trybot.json\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe analyze step does it work by running a custom gyp generator. In order for the analyze step to produce reliable results all dependencies need to be correctly listed. This currently isn't the case for a set of files. For example, data files for tests are not listed as dependencies. Such dependencies are handled by adding them to the exclusions list of the file \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/testing/buildbot/trybot_analyze_config.json\"\u003etrybot_analyze_config.json\u003c/a\u003e .\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eBots that further filter out the set of tests to run based on the changed files is currently opt in. Opt in is done by adding the name of the bot to filter_tests_builders in the appropriate config file for the bot.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3585491094165374254"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/testing/commit-queue/chromium_trybot-json"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7393313184595945406"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7393313184595945406"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7393313184595945406"}],"author":[{"name":{"$t":"Scott Violet"},"email":{"$t":"sky@chromium.org"}}],"sites$pageName":{"$t":"chromium_trybot-json"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3593267020552155936"},"published":{"$t":"2014-07-28T23:45:14.964Z"},"updated":{"$t":"2014-07-28T23:45:15.004Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T23:45:14.964Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image02.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3593267020552155936"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8249727978514538455"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/setup/image02.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3593267020552155936"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3593267020552155936"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3593267020552155936"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3593267020552155936"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6827461749005637284"},"published":{"$t":"2014-07-28T23:43:02.725Z"},"updated":{"$t":"2014-07-28T23:44:48.615Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T23:44:48.594Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image03.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6827461749005637284"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8249727978514538455"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/setup/image03.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6827461749005637284"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6827461749005637284"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6827461749005637284"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6827461749005637284"}],"author":[{}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5786900800067895813"},"published":{"$t":"2014-07-28T23:42:48.313Z"},"updated":{"$t":"2014-07-28T23:42:48.371Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T23:42:48.313Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image00.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5786900800067895813"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8249727978514538455"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/setup/image00.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5786900800067895813"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5786900800067895813"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5786900800067895813"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5786900800067895813"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1501546745723466511"},"published":{"$t":"2014-07-28T23:42:36.407Z"},"updated":{"$t":"2014-07-28T23:42:36.457Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T23:42:36.407Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image01.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1501546745723466511"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8249727978514538455"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/setup/image01.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1501546745723466511"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1501546745723466511"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1501546745723466511"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1501546745723466511"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7051471182340744982"},"published":{"$t":"2014-07-28T23:36:30.386Z"},"updated":{"$t":"2014-07-28T23:36:30.432Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T23:36:30.386Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image01.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7051471182340744982"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8051579724266212911"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/usingmoblab/image01.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7051471182340744982"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7051471182340744982"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7051471182340744982"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7051471182340744982"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4254377874424135961"},"published":{"$t":"2014-07-28T23:36:00.155Z"},"updated":{"$t":"2014-07-28T23:36:00.196Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T23:36:00.155Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image02.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4254377874424135961"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8051579724266212911"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/usingmoblab/image02.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4254377874424135961"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4254377874424135961"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4254377874424135961"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4254377874424135961"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2845075583503170376"},"published":{"$t":"2014-07-28T22:28:11.588Z"},"updated":{"$t":"2014-07-28T22:28:11.644Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T22:28:11.588Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image00.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2845075583503170376"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8051579724266212911"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/usingmoblab/image00.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2845075583503170376"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2845075583503170376"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2845075583503170376"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2845075583503170376"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2310141204650983782"},"published":{"$t":"2014-07-28T22:26:56.399Z"},"updated":{"$t":"2014-07-28T22:26:56.436Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T22:26:56.399Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"image03.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2310141204650983782"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8051579724266212911"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/moblab/usingmoblab/image03.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2310141204650983782"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2310141204650983782"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2310141204650983782"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2310141204650983782"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7499499827193616996"},"published":{"$t":"2013-08-30T19:26:11.063Z"},"updated":{"$t":"2014-07-28T18:18:21.845Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T18:18:21.845Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Writing and Developing Tests"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"5\"\u003e\r\n\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Writing-a-test\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eWriting a test\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Making-a-new-test-work-with-ebuilds\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eMaking a new test work with ebuilds\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Deps\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003eDeps\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Working-on-a-test\"\u003e\u003cstrong\u003e1.3 \u003c/strong\u003eWorking on a test\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Anatomy-of-test.test\"\u003e\u003cstrong\u003e1.4 \u003c/strong\u003eAnatomy of test.test\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Attributes\"\u003e\u003cstrong\u003e1.4.1 \u003c/strong\u003eAttributes\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-initialize-\"\u003e\u003cstrong\u003e1.4.2 \u003c/strong\u003einitialize()\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-setup-\"\u003e\u003cstrong\u003e1.4.3 \u003c/strong\u003esetup()\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-run_once-\"\u003e\u003cstrong\u003e1.4.4 \u003c/strong\u003erun_once()\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-postprocess_iteration-\"\u003e\u003cstrong\u003e1.4.5 \u003c/strong\u003epostprocess_iteration()\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-warmup-\"\u003e\u003cstrong\u003e1.4.6 \u003c/strong\u003ewarmup()\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Test-naming-conventions\"\u003e\u003cstrong\u003e1.5 \u003c/strong\u003eTest naming conventions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003c/font\u003e\u003c/span\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal;background-color:transparent;vertical-align:baseline\"\u003eFor understanding and writing the actual python code for autotest, please refer to the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/writing-and-developing-tests/writing-tests-faq\"\u003eWriting Tests FAQ\u003c/a\u003e.\u003c/span\u003e\r\n\u003cdiv style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13px;font-weight:normal;white-space:normal\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eFor understanding test deps, refer to the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/writing-and-developing-tests/test-deps-faq\"\u003eTest Deps FAQ\u003c/a\u003e.\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13px;font-weight:normal;white-space:normal\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eFor understanding how to test your changes, refer to the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/writing-and-developing-tests/testing-your-changes-faq\"\u003eTesting Your Changes FAQ\u003c/a\u003e.\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003c/span\u003e\r\n\u003ch3 style\u003d\"font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Writing-a-test\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eWriting a test\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eCurrently, all code should be placed in a standard layout inside the autotest.git repository, unless otherwise is necessary for technical reasons. Regardless, the following text assumes that code is placed in generally any repository.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor a test to be fully functional in Chromium OS, it has to be associated with an ebuild. It is generally possible to run tests without an ebuild, either using run_remote_tests --build or calling autoserv directly with the correct options, but discouraged, as the same will not function with other parts of the system.\u003c/span\u003e\u003cbr /\u003e\r\n\u003ch3 style\u003d\"font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Making-a-new-test-work-with-ebuilds\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eMaking a new test work with ebuilds\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe choice of ebuild depends on the location of its sources. Structuring tests into more smaller ebuilds (as opposed to one ebuild per source repository) serves two purposes:\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e- Categorisation - Grouping similar tests together, possibly with deps they use exclusively\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e- Parallelisation - Multiple independent ebuilds can build entirely in parallel\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e- Dependency tracking - Larger bundles of tests depend on more system packages without proper resolution which dependency belongs to which test. This also increases paralellism.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eCurrent ebuild structure is largely a result of breaking off the biggest blockers for parallelism, ie. tests depending on chrome or similar packages, and as such, using any of the current ebuilds should be sufficient. (see FAQ for listing of ebuilds)\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAfter choosing the proper ebuild to add your test into, the test (in the form “+tests_\u0026lt;testname\u0026gt;”) needs to be added to IUSE_TESTS list that all autotest ebuilds have. Failing to do so will simply make ebuilds ignore your tests entirely. As with all USE flags, prepending it with + means the test will be enabled by default, and should be the default, unless you want to keep the test experimental for your own use, or turn the USE flag on explicitly by other means, eg. in a config for a particular board only.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eShould a \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003enew ebuild\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e be started, it should be added to \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003echromeos-base/autotest-all\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e package, which is a meta-ebuild depending on all autotest ebuild packages that can be built. autotest-all is used by the build system to automatically build all tests that we have and therefore keep them from randomly breaking.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003ch3 style\u003d\"font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Deps\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eDeps\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAutotest uses deps to provide a de-facto dependencies into the ecosystem. A dep is a directory in ‘\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eclient/deps\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e’ with a structure similar to a test case without a control file. A test case that depends on a dep will invoke the dep’s setup() function in its own setup() function and will be able to access the files provided by the dep. Note that autotest deps have nothing to do with system dependencies.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs the calls to a dep are internal autotest code, it is not possible to automatically detect these and make them an inter-package dependencies on the ebuild level. For that reason, deps should either be provided by the same ebuild that builds test that consume them, or ebuild dependencies need to be declared manually between the dep ebuild and the test ebuild that uses it. An \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eautotest-deponly\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e eclass exists to provide solution for ebuilds that build only deps and no tests. A number of deponly ebuilds already exist.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eCommon deps are:\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e - chrome_test - Intending to use any of the test binaries produced by chrome.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e - pyauto_dep - Using pyauto for your code.\u003c/span\u003e\u003cbr /\u003e\r\n\u003ch3 style\u003d\"font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Working-on-a-test\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eWorking on a test\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs mentioned, while working on a test, it is necessary to always propagate any source changes using the emerge step. This can be either a manual emerge (instant) or build_packages (longer, rebuilds all dependencies as well).\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFor cros-workon ebuilds, this means first starting to work on all ebuilds that are affected. (\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/building-and-running-tests#TOC-Q5:-I-m-working-on-some-test-sources-how-do-I-know-which-ebuilds-to-cros_workon-start-in-order-to-properly-propagate-\"\u003eWhich ebuilds are these?\u003c/a\u003e):\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"background-color:transparent;font-family:Arial;color:rgb(0,0,255);vertical-align:baseline;white-space:pre-wrap\"\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u003cfont size\u003d\"3\"\u003e$ cros_workon --board\u003d${board} start \u0026lt;list of ebuilds\u0026gt;\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs described, all autotest ebuilds have a selectable list of tests, most of which can be disabled and only the one test that is being worked on can be built selectively, saving time.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-family:Times New Roman;font-weight:bold\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ TESTS\u003dtestname emerge-${board} \u0026lt;list of ebuilds\u0026gt;\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ run_remote_tests.sh --remote\u003d\u0026lt;ip\u0026gt; testname\u003c/code\u003e\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNote:\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e If tests have interdependencies not handled via \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edeps\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, those cannot be automatically detected, and you have to include all tests that are being depended on. An example of that would be an old-style test suite, which is really just a control file calling other tests selectively via hardcoded names. In order to make that work, you have to determine the list of tests accordingly, before you run the suite.\u003c/span\u003e\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Anatomy-of-test.test\" /\u003e\u003cfont face\u003d\"Arial\" size\u003d\"4\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eAnatomy of test.test\u003c/span\u003e\u003c/font\u003e\u003c/h3\u003e\r\n\u003cp\u003eThis section describes the pieces of test.test that are available to use, describing what each does and when it could be used.\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Attributes\" /\u003eAttributes\u003c/h4\u003e\r\n\u003cdiv\u003e       job             backreference to the job this test instance is part of\u003c/div\u003e\r\n\u003cdiv\u003e       outputdir       eg. results/\u0026lt;job\u0026gt;/\u0026lt;testname.tag\u0026gt;\u003c/div\u003e\r\n\u003cdiv\u003e       resultsdir      eg. results/\u0026lt;job\u0026gt;/\u0026lt;testname.tag\u0026gt;/results\u003c/div\u003e\r\n\u003cdiv\u003e       profdir         eg. results/\u0026lt;job\u0026gt;/\u0026lt;testname.tag\u0026gt;/profiling\u003c/div\u003e\r\n\u003cdiv\u003e       debugdir        eg. results/\u0026lt;job\u0026gt;/\u0026lt;testname.tag\u0026gt;/debug\u003c/div\u003e\r\n\u003cdiv\u003e       bindir          eg. tests/\u0026lt;test\u0026gt;\u003c/div\u003e\r\n\u003cdiv\u003e       src             eg. tests/\u0026lt;test\u0026gt;/src\u003c/div\u003e\r\n\u003cdiv\u003e       tmpdir          eg. tmp/\u0026lt;tempname\u0026gt;_\u0026lt;testname.tag\u0026gt;\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-initialize-\" /\u003einitialize()\u003c/h4\u003e\r\n\u003cdiv\u003eEverytime a test runs this function runs. For example, if you have iterations\u003d100 set this will run 100 times. Use this when you need to do something like ensure a package is there. \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-setup-\" /\u003esetup()\u003c/h4\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-setup-\" /\u003e\u003c/h1\u003e\r\n\u003cdiv\u003esetup() runs the first time the test is set up. This is often used for compiling source code one should not need to recompile the source for the test for every iteration or install the same \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-run_once-\" /\u003erun_once()\u003c/h4\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-run_once-\" /\u003e\u003c/h1\u003e\r\n\u003cdiv\u003eThis is called by job.run_test N times, where N is controlled by the interations parameter to run_test (Defaulting to one). it also gets called an additional time with profilers turn on, if any profilers are enabled.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-postprocess_iteration-\" /\u003epostprocess_iteration()\u003c/h4\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-postprocess_iteration-\" /\u003e\u003c/h1\u003e\r\n\u003cdiv\u003eThis processes any results generated by the test iteration and writes them out into a keyval. It's generally not called for the profiling iteration, as that may have difference performance implications.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-warmup-\" /\u003ewarmup()\u003c/h4\u003e\r\n\u003cp\u003e\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003ch3 style\u003d\"font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Test-naming-conventions\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eTest naming conventions\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\r\n\u003cspan style\u003d\"background-color:transparent;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003e(TODO) We don’t have any. These need to be defined and documented here.\u003c/font\u003e\u003c/span\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/writing-and-developing-tests"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7499499827193616996"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7499499827193616996"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7499499827193616996"}],"author":[{}],"sites$pageName":{"$t":"writing-and-developing-tests"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5114108113065684524"},"published":{"$t":"2013-08-30T19:46:22.506Z"},"updated":{"$t":"2014-07-28T18:18:21.836Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-08-30T22:38:29.558Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Testing Your Changes FAQ"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-do-I-test-changes-to-the-Autotest-codebase-itself-\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eHow do I test changes to the Autotest codebase itself?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-do-I-test-changes-to-the-dynamic_suite-infastructure-\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eHow do I test changes to the dynamic_suite infastructure?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-the-fast-way-to-make-a-change-to-a-test-and-iterate-to-see-if-it-now-works-\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eWhat's the fast way to make a change to a test and iterate to see if it now works? \u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-the-fast-way-to-see-if-a-test-now-works-with-tip-of-tree-\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWhat's the fast way to see if a test now works with tip of tree?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-How-do-I-test-changes-to-the-Autotest-codebase-itself-\" /\u003eHow do I test changes to the Autotest codebase itself?\u003c/h2\u003e\u003cdiv\u003eOften times when making changes to the Autotest codebase itself, it is difficult to test your change unless you can actually run an instance of the Autotest server locally.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo quickly get functional Autotest server setup please refer to: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:12ce4d2bddaa8af2\" class\u003d\"disabled\"\u003eSetup Autotest Server\u003c/a\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eReasons to run a local Autotest server might include:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eAutotest Scheduler work\u003c/li\u003e\u003cli\u003eAdding or changing RPCs\u003c/li\u003e\u003cli\u003eTests that involve common library changes\u003c/li\u003e\u003cli\u003eGUI/GWT Frontend work.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-How-do-I-test-changes-to-the-dynamic_suite-infastructure-\" /\u003eHow do I test changes to the dynamic_suite infastructure?\u003c/h2\u003e\u003cdiv\u003eYou'll definitely want a locally-running Autotest server.  For most changes, you will want to start by running the unit tests in server/cros/dynamic_suite as you work.  You may also need to actually run a suite of tests against your Autotest instance.  The 'dummy' suite is ideal, and there are several ways to run it:\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003esite_utils/run_suite.py\u003c/li\u003e\u003cli\u003ecli/atest create_suite_job\u003c/li\u003e\u003cli\u003eserver/autoserv test_suites/dev_harness.py\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eIn the first two cases, there are a variety of command line options and arguments that allow you to set the build and platform to test, etc.  These pathways will always stage a build (if necessary), pull control files from that build, reimage devices and run the desired test suite.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003edev_harness.py does not pull control files from a particular build, but rather uses your local source tree.  If you're trying to test changes to suite control files, for example, this is probably the best way to go.  It can also be configured to skip reimaging, so you can iterate faster.  dev_harness.py is pulled in and executed directly by autoserv, so it can't take command line args.  Instead, it's configured using a file called dev_harness_conf that lives adjacent to dev_harness.py.\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-the-fast-way-to-make-a-change-to-a-test-and-iterate-to-see-if-it-now-works-\" /\u003eWhat's the fast way to make a change to a test and iterate to see if it now works?\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e \u003c/span\u003e\u003c/h2\u003eThe fastest way to develop a test is to \u003ci\u003enot use compiled components\u003c/i\u003e in your test.  If you can write a test without cross-compiling code you can modify the test in python/shell on the target and rerun it on the target directly.  This of course also applies to the situation where you want to modify the python/shell parts of a test that has cross-compiled code.  The point is, try to use the least amount of cross-compiled code to write your test as possible.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAssuming you have done this, on the target device's console, su to root.  Then enter the /home/autotest directory on the target (provided you've run run_remote_tests once with it) and modify the test which will be in the tests subdirectory.  You can run /home/autotest:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px\"\u003e\u003cb\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\u003ccode\u003eon_device# cd /home/autotest; ./bin/autotest tests/system_KernelVersion/control\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003eIf you have modified cross-compiled test code, you can use the above instructions but you'll be rebuilding a lot of stuff you don't need. Instead of running build_platform --withautotest, you can instead just run build_autotest.sh directly (which it calls).  This emerges the autotest cross-compiled binaries.  You can also specify precisely which test you want to rebuild to avoid having to build everything (and wait for it all to finish):\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px\"\u003e\u003cb\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\u003ccode\u003einside# ./build_autotest.sh --board\u003d${BOARD} --build\u003dstorage_Fio,system_SAT\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px\"\u003e\u003cb\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px\"\u003e\u003cb\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003eThe resulting binaries will be placed in your chroot under \u003ccode\u003e${CHROOT}/build/${BOARD}/usr/local/autotest\u003c/code\u003e.   They are not installed into an image at this time.  Instead, autotest will copy them over when you run run_remote_tests.sh.\u003c/span\u003e\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px\"\u003e\u003cspan style\u003d\"font-size:13px\"\u003e\u003cdiv style\u003d\"display:inline!important\"\u003e\u003cdiv style\u003d\"display:inline!important\"\u003e\u003ch2 style\u003d\"font-weight:normal\"\u003e\u003ca name\u003d\"TOC-What-s-the-fast-way-to-see-if-a-test-now-works-with-tip-of-tree-\" /\u003e\u003cb\u003eWhat's the fast way to see if a test now works with tip of tree?\u003c/b\u003e\u003c/h2\u003e\u003c/div\u003e\u003c/div\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003eThe best way is to prepare a CL and test it using \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/build/local-trybot-documentation\"\u003etrybots\u003c/a\u003e.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7499499827193616996"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/writing-and-developing-tests/testing-your-changes-faq"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5114108113065684524"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5114108113065684524"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5114108113065684524"}],"author":[{}],"sites$pageName":{"$t":"testing-your-changes-faq"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6659229897558489506"},"published":{"$t":"2013-08-29T20:52:15.612Z"},"updated":{"$t":"2014-07-28T18:18:13.137Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T18:18:13.137Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Specific Test Documentation"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eDocumentation for specific kinds of testing is under this directory.\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/specific-test-documentation"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6659229897558489506"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6659229897558489506"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6659229897558489506"}],"author":[{}],"sites$pageName":{"$t":"specific-test-documentation"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7385154061834713093"},"published":{"$t":"2013-08-30T18:24:17.678Z"},"updated":{"$t":"2014-07-28T18:18:04.996Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-08-30T18:25:35.533Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Keyvals"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eJob keyvals are key/value pairs, used to cache/exchange data about jobs between different services in autotest, via the database. There are two keyvals tables, \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eafe_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e and\u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e tko_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e. Both tables have a \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ejob_id\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e column for keyvals to be foreign keyed to a job. The\u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e job_id\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e can be a suite job id if jobs are queued by a suite run, or test job id if the job is queued directly from atest/run_remote_test/autoserv.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eThe initial job keyvals get specified as part of the arguments to the \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003ecreate_job\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e RPC and entered into the database (into the \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eafe_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e table). Then, before we go to run a job, we pull the keyvals out of the database and write them to a file. This is done by a class named \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eTaskWithJobKeyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e that is a mixin that gets included for the \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eAgent\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003es representing job runs. The parsing of these keyvals back into the database happens when the scheduler kicks off \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003etko/parse.py\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e to parse job results during the \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003ePARSING\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e phase. \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003etko/parse.py\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e calls \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003etko/db.py:insert_job()\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e, which contains the call to \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eupdate_job_keyvals()\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e which does the actual j\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eo\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eb keyval \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewriting. Th\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eese get inserted into \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003etko_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e, so the initial keyvals are always in \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eafe_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e, and the final results in \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003etko_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eafe_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e stores the a job's suite and build information. \u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Courier New;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003etko_job_keyvals\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e stores the test result information, including: \u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003euser that requested the job\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003ejob start/end time (job_started, job_queued, job_finished)\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003eperf keyvals, which are up to individual tests to create as they see fit. The use and lifecycle of perf keyvals is explained in detail on \u003c/span\u003e\u003cspan style\u003d\"text-decoration:underline;font-family:Arial;color:rgb(17,85,204);vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:34d4f97c5b51d664\" class\u003d\"disabled\"\u003ea separate webpage\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:4pt;margin-bottom:0pt;margin-right:11pt\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eImportantly, the tko_job_keyvals entry for a suite job stores a dictionary between hashed test names and job_id-owner. After a suite job is finished, run_suite uses this dictionary to find out the job url for a particular test. The reason for this is that when a suite is started, all keyvals are keyed by suite job id. The test job id is set only after the test job is started.  After a test job has finished, autoserv creates logs a keyval (for the test’s job id) with the hashed test name as the key and job_id-owner as the value. run_suite pulls the keyval from tko_job_keyval table and maps the test job to its result page, which is the test job page, rather than suite job page.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(34,34,34);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8391995747890207487"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/infrastructure-components/keyvals"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7385154061834713093"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7385154061834713093"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7385154061834713093"}],"author":[{}],"sites$pageName":{"$t":"keyvals"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3735152850111372443"},"published":{"$t":"2013-08-29T20:18:51.437Z"},"updated":{"$t":"2014-07-28T18:17:16.720Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T18:17:16.720Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Dynamic Suites"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eDocumentation about dynamic test suites is under this directory.\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/dynamic-suites"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3735152850111372443"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3735152850111372443"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3735152850111372443"}],"author":[{}],"sites$pageName":{"$t":"dynamic-suites"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9132967561816938698"},"published":{"$t":"2013-08-29T20:10:45.469Z"},"updated":{"$t":"2014-07-28T18:17:16.710Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-08-29T20:20:32.520Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Test Dependencies in Dynamic Suites"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-DEPENDENCIES-in-autotest-control-files-today\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eDEPENDENCIES in autotest control files today\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-DEPENDENCIES-in-dynamic-suites\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eDEPENDENCIES in dynamic suites\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Scheduling-tests-on-appropriate-hosts\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eScheduling tests on appropriate hosts\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Determining-which-machines-to-reimage-for-a-suite\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eDetermining which machines to reimage for a suite\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-The-naive-algorithm-in-broad-strokes-\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eThe naive algorithm (in broad strokes)\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-No-it-s-not-a-set-cover-problem\"\u003e\u003cstrong\u003e2.3.1 \u003c/strong\u003eNo, it’s not a set-cover problem\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-A-dead-stupid-first-pass-read:-what-we-ve-implemented-so-far-\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003eA dead-stupid first pass (read: what we've implemented so far!)\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003eNot all tests can be run on all machines.  Currently, the dynamic suite infrastructure has no way to deal with this issue.  Our intent is to use the existing autotest control file DEPENDENCIES field to express what a test needs in order to be able to run.  Any label in use in the autotest lab is valid in a test’s DEPENDENCIES list.\u003ch1 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-DEPENDENCIES-in-autotest-control-files-today\" /\u003e\u003cspan style\u003d\"font-size:24px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDEPENDENCIES in autotest control files today\u003c/span\u003e\u003c/h1\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eCurrently, it seems that DEPENDENCIES in control files are parsed in only when tests are imported for use via the web front end, and they (may be) honored when tests are scheduled via that method.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDependencies can also be specified when running a test via the create_job() RPC exposed by the AFE. \u003c/span\u003e\u003cbr /\u003e\u003ch1 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-DEPENDENCIES-in-dynamic-suites\" /\u003e\u003cspan style\u003d\"font-size:24px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDEPENDENCIES in dynamic suites\u003c/span\u003e\u003c/h1\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere are two, related, issues here.  One is how individual tests will declare the things they need from a host in order to run, and how the dynamic suite infrastructure will schedule these tests on appropriate machines.  The second, more complex issue, is how the dynamic suites code will ensure that -- for a given suite -- it reimages a set of hosts that will enable all tests in the suite to be scheduled.\u003c/span\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Scheduling-tests-on-appropriate-hosts\" /\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eScheduling tests on appropriate hosts\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs the dynamic suite code is already parsing each individual test control file it intends to run, it will not be too hard for it to add the contents of DEPENDENCIES to the metahost spec that it already builds up when scheduling tests with the create_job() RPC.\u003c/span\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-Determining-which-machines-to-reimage-for-a-suite\" /\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDetermining which machines to reimage for a suite\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere are several parameters that will inform dynamic suites’ decision about which machines to reimage for a suite:\u003c/span\u003e\u003cbr /\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ethe board being tested,\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ethe number of machines the suite asks to use, and\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ethe collective dependencies of all tests in the suite.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThese criteria introduce some new potential failure modes for suites:\u003c/span\u003e\u003cbr /\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ethere is at least one test with unsatisfiable dependencies\u003c/span\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWe should just fast-fail the suite, because we're not going to be able to complete it.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eall dependencies are satisfiable, but not by the number of machines requested\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eall dependencies can be satisfied by \u0026lt; num machines, but none of the remaining machines satisfy any tests in the suite\u003c/span\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003econsider a bluetooth test suite that wants two machines, but we have only one machine with bluetooth\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere are also some resource efficiency concerns here:\u003c/span\u003e\u003cbr /\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eMachines with rare labels, or label combos, should be avoided if possible\u003c/span\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe only i5 lumpy with a Y3400 modem and swedish keyboard should not be used when an i5 wifi-only lumpy from any region will do\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOne test in a suite with a rare label should not lead to the suite monopolizing all hosts with that label\u003c/span\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ea suite that asks for 4 machines and has 15 tests that will run anywhere and one that requires GOBI2K should grab 1 GOBI2K device and 3 wifi-only ones.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ol\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-The-naive-algorithm-in-broad-strokes-\" /\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe naive algorithm (in broad strokes)\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere’s a set of machines in the lab, each of which is described by a set of labels  There’s also a suite (read: set) of tests, each of which is described by a set of labels (read: dependencies).  For a given N, we need to find a set of N machines such that the dependencies of each test in the suite are satisfied by some machine in the set.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe difficulty is that we want to use ‘rare’ machines only if we really need them.  If we weight hosts somehow, this should allow us to build a scoring function that we can use in a simulated annealing or hill-climbing kind of approximation algorithm.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-No-it-s-not-a-set-cover-problem\" /\u003e\u003cspan style\u003d\"font-size:16px;font-family:Arial;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNo, it’s not a set-cover problem\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAt first blush, this problem felt to me like a set-cover problem.  Merge all the dependencies of all tests in the suite into a single, de-dup’d list, and then find the smallest number of devices whose label sets covered the whole she-bang.  The problem is that this algorithm could provide a solution that leaves some tests unsatisfied.  Consider the following example:\u003c/span\u003e\u003cbr /\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ctable style\u003d\"border:none;border-collapse:collapse;width:624px\"\u003e\u003ccolgroup\u003e\u003ccol width\u003d\"*\" /\u003e\u003ccol width\u003d\"*\" /\u003e\u003c/colgroup\u003e\u003ctbody\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eTest Dependencies\u003c/span\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eHost Labels\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e[RPM, BT, GOBI3K]\u003c/span\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e[RPM, BT, GOBI3K]\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:0px\"\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e[RPM, BT, i5]\u003c/span\u003e\u003c/td\u003e\u003ctd style\u003d\"border:1px solid rgb(0,0,0);padding:7px\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e[RPM, i5]\u003c/span\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis algorithm would merge the test deps into [RPM, BT, GOBI3K, i5], and determine that choosing both hosts would successfully cover.  The problem is that the second test cannot be run in this testbed, as no machine meets all its dependencies.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\"\u003e\u003ca name\u003d\"TOC-A-dead-stupid-first-pass-read:-what-we-ve-implemented-so-far-\" /\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA dead-stupid first pass (read: what we've implemented so far!)\u003c/span\u003e\u003c/h2\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSince we only have tests with a single dependency these days, we’re going to start by gathering all the deps of all the tests in the suite, de-duping them, and finding \u0026lt;\u003d N machines to satisfy those deps.  We may try to be smart about how we pad out the machines to reach N, if we can.  If we have 10 Gobi3K tests and 2 Gobi2K tests, and N \u003d\u003d 3, then we might try to get 2 Gobi3K devices and 1 Gobi2K, for example.  If we can satisfy all tests with \u0026lt; N devices, and cannot pad to reach N total devices, we’ll WARN, but continue to run the suite.\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3735152850111372443"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/dynamic-suites/test-dependencies-in-dynamic-suites"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9132967561816938698"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9132967561816938698"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9132967561816938698"}],"author":[{}],"sites$pageName":{"$t":"test-dependencies-in-dynamic-suites"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2801344393645836933"},"published":{"$t":"2013-08-29T20:49:00.471Z"},"updated":{"$t":"2014-07-28T18:17:04.188Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T18:17:04.188Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Common Testing Workflows"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Workflow-1\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eWorkflow 1\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-already-has-a-built-system-using-build-instructions.-Developer-wants-to-create-a-copy-of-their-image-for-testing-and-build-Chromium-OS-tests-without-re-running-build_packages.\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003eDeveloper already has a built system using build instructions. Developer wants to create a copy of their image for testing and build Chromium OS tests without re-running build_packages.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-cros_sdk-and-run-mod_image_for_test-on-the-chromiumos_image.bin-if-you-get-complaints-of-unmount-errors-sudo-umount-media-outside-the-chroot-.\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003ecros_sdk and run mod_image_for_test on the chromiumos_image.bin (if you get complaints of unmount errors, sudo umount /media/* outside the chroot).\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Workflow-2\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eWorkflow 2\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Workflow-3\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eWorkflow 3\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-wants-to-run-a-test-with-certain-conditions-met-on-the-host-system-before-the-system-is-ready-for-that-test-e.g.-browser-is-not-running-and-has-never-run-since-boot-.\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eDeveloper wants to run a test with certain conditions met on the host system before the system is ready for that test e.g. \"browser is not running and has never run since boot\".\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-For-tests-that-require-system-wide-setup-and-system-wide-cleanup-the-best-approach-is-probably-to-create-a-server-side-test-that-sets-up-the-environment-reboots-the-system-runs-the-test-and-cleans-up-the-system.-This-should-not-be-done-for-very-small-tests\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eFor tests that require system-wide setup and system-wide cleanup, the best approach is probably to create a server-side test that sets up the environment, reboots the system, runs the test and cleans up the system.  This should not be done for very small tests as rebooting is rather expensive.  Take a look at BootPerfServer as an example to write such a test.\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Workflow-4\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eWorkflow 4\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-W1.-Develop-and-iterate-on-a-test\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eW1. Develop and iterate on a test\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-W2.-Creating-a-test---steps-and-checklist\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eW2. Creating a test - steps and checklist\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-W3.-Splitting-autotest-ebuild-into-two\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003eW3. Splitting autotest ebuild into two\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-W4.-Create-and-run-a-test-enabled-image-on-your-device\"\u003e\u003cstrong\u003e4.4 \u003c/strong\u003eW4. Create and run a test-enabled image on your device\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003eThere are a lot of common developer workflows when it comes to testing.  This document details those.\u003ch2\u003e\u003ca name\u003d\"TOC-Workflow-1\" /\u003eWorkflow 1\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-already-has-a-built-system-using-build-instructions.-Developer-wants-to-create-a-copy-of-their-image-for-testing-and-build-Chromium-OS-tests-without-re-running-build_packages.\" /\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e\u003ci\u003eDeveloper already has a built system using build instructions. Developer wants to create a copy of their image for testing and build Chromium OS tests without re-running build_packages.\u003c/i\u003e\u003c/span\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-cros_sdk-and-run-mod_image_for_test-on-the-chromiumos_image.bin-if-you-get-complaints-of-unmount-errors-sudo-umount-media-outside-the-chroot-.\" /\u003e\u003cfont size\u003d\"3\"\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal\"\u003ecros_sdk and run mod_image_for_test on the chromiumos_image.bin (if you get complaints of unmount errors, sudo umount /media/* outside the chroot).\u003c/span\u003e\u003c/font\u003e\u003c/h3\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Workflow-2\" /\u003eWorkflow 2\u003c/h2\u003e\u003ci\u003eDeveloper has a testable image on their device. Developer makes modifications to the python component of a test and wants to re-run the test on the target system.\u003c/i\u003e\u003cdiv\u003e\u003ci\u003e\u003cbr /\u003e\u003c/i\u003e\u003cdiv\u003eIf the user makes modifications on the host system, the easiest way to re-run the tests is to re-run run_remote_tests.  That script takes local changes from third_party/autotest before running tests.  However, if the developer wants to make changes to dependencies of their tests, the developer must re-run build_autotest.sh\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Workflow-3\" /\u003eWorkflow 3\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-wants-to-run-a-test-with-certain-conditions-met-on-the-host-system-before-the-system-is-ready-for-that-test-e.g.-browser-is-not-running-and-has-never-run-since-boot-.\" /\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e\u003ci\u003eDeveloper wants to run a test with certain conditions met on the host system before the system is ready for that test e.g. \"browser is not running and has never run since boot\".\u003c/i\u003e\u003c/span\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-For-tests-that-require-system-wide-setup-and-system-wide-cleanup-the-best-approach-is-probably-to-create-a-server-side-test-that-sets-up-the-environment-reboots-the-system-runs-the-test-and-cleans-up-the-system.-This-should-not-be-done-for-very-small-tests\" /\u003e\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003eFor tests that require system-wide setup and system-wide cleanup, the best approach is probably to create a server-side test that sets up the environment, reboots the system, runs the test and cleans up the system.  This should not be done for very small tests as rebooting is rather expensive.  Take a look at \u003ca href\u003d\"http://git.chromium.org/cgi-bin/gitweb.cgi?p\u003dautotest.git;a\u003dtree;f\u003dserver/site_tests/platform_BootPerfServer;h\u003d2362958081700ed3e243935641ebe69b17890045;hb\u003dHEAD\"\u003eBootPerfServer\u003c/a\u003e as an example to write such a test.\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003eNote in the long run we want to create utilities that verify certain conditions.  If you are interested in writing one of these utilities, please email the dev list.\u003c/i\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Workflow-4\" /\u003eWorkflow 4\u003c/h2\u003e\u003ci\u003eDeveloper wants to run a test that requires a user to be logged in.\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\u003cbr /\u003e\u003c/i\u003e\u003cdiv\u003eSubclass your test from site_ui_test.UITest\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003eNote we are trying to create a utility for such pre-req's as login, so make sure to leave a big todo with DoLogin in it so that we can update your tests once they the utility libraries are ready.\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\u003cbr /\u003e\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Times New Roman\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-W1.-Develop-and-iterate-on-a-test\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eW1. Develop and iterate on a test\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e0. Set up environment\u003c/span\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:bold;font-size:medium\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ cd ~/trunk/src/third_party/autotest/files/\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ export TESTS\u003d”\u0026lt;the test cases to iterate on\u0026gt;”\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ EBUILD\u003d\u0026lt;the ebuild that contains TEST\u0026gt;\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ board\u003d\u0026lt;the board on which to develop\u0026gt;\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1. Ensure cros_workon is started\u003c/span\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:bold;font-size:medium\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ cros_workon --board\u003d${board} start ${EBUILD}\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ repo sync # Necessary only if you use minilayout.\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2. Make modifications (on first run, you may want to just do 3,4 to verify everything works before you touch it \u0026amp; break it)\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ …\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3. Build test (TESTS\u003d is not necessary if you exported it before)\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ emerge-$board $EBUILD\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4. Run test to make sure it works before you touch it\u003c/span\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:bold;font-size:medium\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ run_remote_tests --remote\u003d\u0026lt;machine IP\u0026gt; --use_emerged ${TEST\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003eS}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5. Go to 2) to iterate\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6. Clean up environment\u003c/span\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"font-weight:bold;font-size:medium\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ cros_workon --board\u003d${board} stop ${EBUILD}\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ unset TESTS\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch3 style\u003d\"font-size:medium\"\u003e\u003ca name\u003d\"TOC-W2.-Creating-a-test---steps-and-checklist\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eW2. Creating a test - steps and checklist\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhen creating a test, the following steps should be done/verified.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e1. Create the actual test directory, main test files/sources, at least one control file\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e2. Find the appropriate ebuild package and start working on it:\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ cros_workon --board\u003d${board} start \u0026lt;package\u0026gt;\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3. Add the new test into the IUSE_TESTS list of 9999 ebuild\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4. Try building: (make sure it’s the 9999 version being built)\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ TESTS\u003d\u0026lt;test\u0026gt; emerge-$board \u0026lt;package\u0026gt;\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003c/span\u003e\u003cfont size\u003d\"3\"\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e5. Try running:\u003c/font\u003e\u003cb style\u003d\"font-size:medium;font-family:Times New Roman\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ccode\u003e$ run_remote_tests.sh --remote\u003d\u0026lt;IP\u0026gt; --use_emerged \u0026lt;test\u0026gt;\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv\u003e\u003cb style\u003d\"font-size:medium;font-family:Times New Roman\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e6. Iterate on 4,5 and modify source until happy with the initial version.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e7. Commit test source first, when it is safely in, commit the 9999 ebuild version change.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e8. Cleanup\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ cros_workon --board\u003d${board} stop \u0026lt;package\u0026gt;\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-W3.-Splitting-autotest-ebuild-into-two\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eW3. Splitting autotest ebuild into two\u003c/span\u003e\u003c/h3\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eRemoving a test from one ebuild and adding to another in the same revision causes portage file collisions unless counter-measures are taken. Generally, some things routinely go wrong in this process, so this checklist should serve to help that.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e0. We have ebuild \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003efoo-0.0.1-r100\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e with \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etest\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e and would like to split that test off into ebuild\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e bar-0.0.1-r1\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eAssume that:\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e- both ebuilds are using cros-workon (because it’s likely the case).\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e- foo is used globally (eg. autotest-all depends on it), rather than just some personal ebuild\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e1. Remove \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etest\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e from foo-{0.0.1-r100,9999}; uprev foo-0.0.1-r100 (to -r101)\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e2. Create bar-9999 (making a copy of foo and replacing IUSE_TESTS may be a good start), with IUSE_TESTS containing just the entry for \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003etest\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e3. Verify package dependencies of test. Make bar-9999 only depend on what is needed for test, remove the dependencies from foo-9999, unless they are needed by tests that remained.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e4. Add a blocker. Since bar installs files owned by foo-0.0.1-r100 and earlier, the blocker’s format will be:\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(0,0,255);background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eRDEPEND\u003d”!\u0026lt;\u003dfoo-0.0.1-r100”\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e5. Add a dependency to the new version of bar into chromeos-base/autotest-all-0.0.1\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eRDEPEND\u003d”bar”\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e6. Change the dependency of foo in chromeos-base/autotest-all-0.0.1 to be version locked to the new rev:\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eRDEPEND\u003d”\u0026gt;foo-0.0.1-r100”\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e7. Uprev (move) autotest-all-0.0.1-rX symlink by one.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e8. Publish all as the same change list, have it reviewed, push.\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003ch3 style\u003d\"font-size:15px\"\u003e\u003ca name\u003d\"TOC-10\" /\u003e\u003cbr /\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-W4.-Create-and-run-a-test-enabled-image-on-your-device\" /\u003e\u003cfont size\u003d\"4\"\u003e\u003ca name\u003d\"TOC-W4.-Create-and-run-a-test-enabled-image-on-your-device\" /\u003eW4. Create and run a test-enabled image on your device\u003c/font\u003e\u003c/h3\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e1. Choose which board you want to build for (we'll refer to this as ${BOARD}, which is for example \"x86-generic\").\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e2. Set up a proper portage build chroot setup.  Go through the normal process of setup_board if you haven't already. \u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ ./build_packages --board\u003d${BOARD}\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e3. Build test image.\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ ./build_image --board\u003d${BOARD} test\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e4. Install the Chromium OS testing image to your target machine.  This is through the standard mechanisms: either USB, or by reimaging a device currently running a previously built Chromium OS image modded for test, or by entering the shell on the machine and forcing an auto update to your machine when it's running a dev server.  For clarity we'll walk through two common ways below, but if you already know about this, just do what you normally do.\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e4a. If you choose to use a USB boot, you first put the image on USB and run this from outside the chroot.\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ cros flash --board\u003d${BOARD} usb:// chromiumos_test_image.bin\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e4b. Alternatively, if you happen to already have a machine running an image modified for test and you know its IP address (${REMOTE_IP}), you can avoid using a USB key and reimage it with a freshly built image by running this from outside the chroot:\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ ./image_to_live.sh --remote\u003d${REMOTE_IP} --image\u003d`./get_latest_image.sh --board\u003d${BOARD}`/chromiumos_test_image.bin\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:15px\"\u003eThis will automatically start dev server, ssh to your machine, cause it to update to from that dev server using memento_updater, reboot, wait for reboot, print out the new version updated to, and shut down your dev server.\u003c/div\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/common-testing-workflows"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2801344393645836933"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2801344393645836933"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2801344393645836933"}],"author":[{}],"sites$pageName":{"$t":"common-testing-workflows"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3887103025567847521"},"published":{"$t":"2013-08-30T19:21:47.470Z"},"updated":{"$t":"2014-07-28T18:16:15.478Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T18:16:15.477Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Autotest and Ebuilds"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cfont size\u003d\"5\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:350px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Useful-documents\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eUseful documents\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Autotest-and-ebuild-workflow\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eAutotest and ebuild workflow\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Overview\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eOverview\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Ebuild-setup-autotest-eclass\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eEbuild setup, autotest eclass\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Useful-documents\" /\u003e\u003cfont size\u003d\"5\"\u003eUseful documents\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eAutotest documentation on GitHub - \u003c/span\u003e\u003c/font\u003e\u003cb style\u003d\"font-family:Times New Roman\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003ca href\u003d\"https://github.com/autotest/autotest/wiki/AutotestApi\" rel\u003d\"nofollow\"\u003ehttps://github.com/autotest/autotest/wiki/AutotestApi\u003c/a\u003e\u003c/span\u003e\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e  This would be a good read if you want to familiarize yourself with the basic Autotest concepts\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003eGentoo Portage ebuild/eclass Information - \u003ca href\u003d\"http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part\u003d2\" rel\u003d\"nofollow\"\u003ehttp://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part\u003d2\u003c/a\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e  Getting to know the package build system we use.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003eChromiumOS specific Portage FAQ - \u003ca href\u003d\"http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/portage-build-faq\"\u003ehttp://www.chromium.org/chromium-os/how-tos-and-troubleshooting/portage-build-faq\u003c/a\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e  Learning something about the way we use portage.\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-family:Times New Roman\"\u003e\u003ch2 style\u003d\"font-size:medium\"\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h2\u003e\u003ch2 style\u003d\"font-size:medium\"\u003e\u003ca name\u003d\"TOC-2\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Autotest-and-ebuild-workflow\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eAutotest and ebuild workflow\u003c/font\u003e\u003c/span\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eTo familiarize with autotest concepts, you should start with the upstream Autotest documentation at: \u003c/span\u003e\u003ca href\u003d\"https://github.com/autotest/autotest/wiki/AutotestApi\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003ehttps://github.com/autotest/autotest/wiki/AutotestApi\u003c/span\u003e\u003c/a\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eThe rest of this document is going to use some terms and only explain them vaguely.\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\u003ch3 style\u003d\"font-size:medium\"\u003e\u003ca name\u003d\"TOC-3\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Overview\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eOverview\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cbr /\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eAt a high level, tests are organized in test cases, each test case being either server or client, with one main .py file named the same as the test case, and one or more control files. In order to be able to perform all tasks on a given test, autotest expects tests to be placed in a monolithic file structure of:\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e/client/tests/\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e/client/site_tests/\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e/server/tests/\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e/server/site_tests/\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eEach test directory has to have at least a control file, but typically also has a main job module (named the same as the test case). Furthermore, if it needs any additional files checked in, they are typically placed in a files/ directory, and separate projects that can be built with a Makefile inside the src/ directory.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eDue to structural limitations in Chromium OS, it is not possible to store all test cases in this structure in a single large source repository as upstream autotest source would (placed at \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003ethird_party/autotest/files/\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e in Chromium OS). In particular, the following has been required in the past:\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e- Having confidential (publicly inaccessible) tests or generally per-test ACLs for sharing only with a particular partner only.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e- Storing test cases along with the project they wrap around, because the test requires binaries built as a by-product of the project’s own build system. (fe. chrome or tpm tests)\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eFurthermore, it has been desired to generally build everything that is not strongly ordered in parallel, significantly decreasing build times. That, however, requires proper dependency tree declaration and being able to specify which test cases require what dependencies, in addition to being able to process different “independent” parts of a single source repository in parallel.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eThis leads to the ebuild workflow, which generally allows compositing any number of sources in any format into a single monolithic tree, whose contents depend on build parameters.\u003c/span\u003e\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;white-space:pre-wrap\"\u003e\u003cdiv style\u003d\"text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/autotest-user-doc/atest-diagram.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1337270405104/chromium-os/testing/autotest-user-doc/atest-diagram.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:5px;margin-bottom:5px;margin-right:auto\" /\u003e\u003c/span\u003e\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eThis allows using standard autotest workflow without any change, however, unlike what upstream does, the tests aren’t run directly from the source repository, rather from a staging read-only install location. This leads to certain differences in workflow:\u003c/font\u003e\u003c/span\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:bold;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cp\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eSource may live in an arbitrary location or can be generated on the fly. Anything that can be created as an ebuild (shell script) can be a test source. (cros-workon may be utilised, introducing a fairly standard Chromium OS project workflow)\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eThe staging location (/build/${board}/usr/local/autotest/) may not be modified; if one wants to modify it, they have to find the source to it (using other tools, see FAQ).\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cp\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003ePropagating source changes requires an emerge step.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"font-size:16px\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-size:16px\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch3 style\u003d\"font-family:Times New Roman\"\u003e\u003ca name\u003d\"TOC-Ebuild-setup-autotest-eclass\" /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"4\"\u003eEbuild setup, autotest eclass\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eNOTE:\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e This assumes some basic knowledge of how ebuilds in Chromium OS work. Refer to for example \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/portage-build-faq\" style\u003d\"font-family:Times New Roman;font-weight:bold\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(17,85,204);background-color:transparent;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003ehttp://www.chromium.org/chromium-os/how-tos-and-troubleshooting/portage-build-faq\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e for some documentation.\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAn \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eautotest ebuild\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is an ebuild that produces test cases and installs them into the \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003estaging area\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e. It has three general tasks:\u003c/span\u003e\u003c/font\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:bold;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eObtain the source - This is generally (but not necessarily) provided by ‘cros-workon’ eclass. It could also work with the more standard tarball SRC_URI pathway or generally any shell code executed in src_unpack().\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003ePrepare test cases - This includes, but is not limited to preprocessing any source, copying source files or intermediate binaries into the expected locations, where they will be taken over by autotest code, specifically the setup() function of the appropriate test. Typically, this is not needed.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eCall autotest to ‘build’ all sources and subsequently install them - This should be done exclusively by inheriting the \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eautotest eclass\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, which bundles up all the necessary code to install into the intermediate location.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAutotest eclass\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is inherited by all autotest ebuilds, only requires a number of variables specified and works by itself otherwise. Most variables describe the locations and listings of work that needs to be done:\u003c/span\u003e\u003c/font\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:bold;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eLocation variables define the paths to directories containing the test files:\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAUTOTEST_{CLIENT,SERVER}_{TESTS,SITE_TESTS}\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAUTOTEST_{DEPS,PROFILERS,CONFIG}\u003c/span\u003e\u003cbr /\u003e\u003c/font\u003e\u003cp dir\u003d\"ltr\" style\u003d\"font-family:Times New Roman;font-weight:bold;margin-left:36pt;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eThese typically only need to be specified if they differ from the defaults (which follow the upstream directory structure)\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:bold;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eList variables (AUTOTEST_*_LIST) define the \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003elist\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e of deps, profilers, configs that should be handled by this ebuild.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eIUSE test list specification TESTS\u003d, is a USE_EXPANDed specification of tests managed by the given ebuild. By virtue of being an IUSE variable, all of the options are visible as USE flag toggles while building the ebuild, unlike with list variables which are a given and the ebuild has to be modified for those to change.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eEach ebuild usually operates on a single source repository. That does not always have to hold true, however, and in case of autotest, many ebuilds check out the sources of the same source repository (\u003ci\u003eautotest.git\u003c/i\u003e). Invariably, this means that they have to be careful to not install the same files and split the sources between themselves to avoid file install collisions.\u003c/span\u003e\u003cbr /\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf more than one autotest ebuild operates on the same source repository, they \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ehave to\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e use the above variables to define mutually exclusive slices in order to not collide during installation. Generally, if we have a source repository with client site_tests A and B, you can have either:\u003c/span\u003e\u003c/font\u003e\u003cul style\u003d\"font-family:Times New Roman;font-weight:bold;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eone ebuild with IUSE_TESTS\u003d”+tests_A +tests_B”\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli style\u003d\"list-style:disc;font-family:Arial;background-color:transparent;font-weight:normal;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003etwo different ebuilds, one with IUSE_TESTS\u003d”+tests_A”, the other with IUSE_TESTS\u003d”+tests_B”\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs soon as an overlap between ebuilds happens, either an outside mechanism has to ensure the overlapping tests are never enabled at the same time, or file collisions happen.\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/autotest-and-ebuilds"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3887103025567847521"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3887103025567847521"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3887103025567847521"}],"author":[{}],"sites$pageName":{"$t":"autotest-and-ebuilds"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/607117666182967889"},"published":{"$t":"2011-04-20T16:33:36.614Z"},"updated":{"$t":"2014-07-28T16:34:41.184Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-28T16:34:39.838Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Updating the Release Notes"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"margin-left:1em\"\u003e\u003cp\u003eThis page has some tips on figuring out what's changed between two releases. I've used this technique to update the \u003ca href\u003d\"http://code.google.com/chrome/extensions/whats_new.html\"\u003eWhat's New\u003c/a\u003e page in the extensions doc, but the technique is more generally useful. \u003c/p\u003e\u003cp\u003eTo see what's changed between two releases (e.g. M9 and M10):\u003c/p\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-left:1em\" /\u003e\u003cdiv style\u003d\"margin-left:1em\"\u003e\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003eGo to \u003ca href\u003d\"https://omahaproxy.appspot.com/viewer\" style\u003d\"color:rgb(0,102,204)!important\"\u003ehttps://omahaproxy.appspot.com/viewer\u003c/a\u003e, and get the current versions of the two releases. E.g.:\u003c/li\u003e\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003eM9 (win stable): 9.0.597.107\u003c/li\u003e\u003cli\u003eM10 (win beta): 10.0.648.119\u003cbr /\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ol\u003e\u003cli\u003eGo to \u003ca href\u003d\"https://omahaproxy.appspot.com/changelog\" style\u003d\"color:rgb(0,102,204)!important\"\u003ehttps://omahaproxy.appspot.com/changelog\u003c/a\u003e, enter the versions in the fields, and click \u003cb\u003eGet SVN logs\u003c/b\u003e. E.g.:\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003eOld Version: 9.0.597.107\u003c/li\u003e\u003cli\u003eNew Version: 10.0.648.119\u003c/li\u003e\u003cli\u003e\u0026lt;click!\u0026gt;\u003cbr /\u003eYou'll see a big page of revisions, with a revision range (e.g. 67679:72316).\u003c/li\u003e\u003cli\u003eSearch for interesting strings in this page, and open relevant links to check whether they're worth talking about.\u003cbr /\u003e\u003cbr /\u003e\u003cb\u003eNote:\u003c/b\u003e This tells you the differences between these branches at the time the branches were created. If you substitute 1 for the last tuple of each version #, you get exactly the same information.\u003cbr /\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli\u003eDo #2 again, but this time change the old version to be the same as the new version, but with a 1 as the last tuple. E.g.:\u003c/li\u003e\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003eOld Version: 10.0.648.1\u003c/li\u003e\u003cli\u003eNew Version: 10.0.648.119\u003c/li\u003e\u003cli\u003e\u0026lt;click!\u0026gt;\u003cbr /\u003eYou'll see another page of revisions with a different (higher) revision range (e.g. 72323:75907).\u003c/li\u003e\u003cli\u003eSearch for interesting strings in this page.\u003cbr /\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ol\u003e\u003cli\u003eOnce you have a list of probable changes, make sure they weren't merged into the previous release. One way to do this is to do #3 again, using the previous release's numbers. E.g.:\u003c/li\u003e\u003col style\u003d\"list-style-type:decimal\"\u003e\u003cli\u003eOld Version: 9.0.597.1\u003c/li\u003e\u003cli\u003eNew Version: 9.0.597.107\u003c/li\u003e\u003cli\u003e\u0026lt;click!\u0026gt;\u003c/li\u003e\u003cli\u003eSearch for the revision #s you found interesting in steps 2 \u0026amp; 3. If you find something that \u003ci\u003ewas \u003c/i\u003ebackported, make sure it's in the release notes for the old release (if it's worthy).\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-left:1em\"\u003e\u003cdiv\u003eThe most useful strings strings to search for (for extensions/apps release notes):\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-left:1em\"\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003esrc/chrome/common/extensions/\u003c/li\u003e\u003cli\u003econtent script\u003c/li\u003e\u003cli\u003etheme [haven't done this in the past, but we really should]\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eI used to also/instead search for these:\u003c/div\u003e\u003cul\u003e\u003cli\u003eextension_api.json\u003c/li\u003e\u003cli\u003epermission\u003c/li\u003e\u003cli\u003emanifest\u003c/li\u003e\u003cli\u003eextensions/docs\u003c/li\u003e\u003cli\u003epackaged app\u003c/li\u003e\u003cli\u003ehosted app\u003c/li\u003e\u003cli\u003eapps\u003c/li\u003e\u003cli\u003etheme\u003c/li\u003e\u003cli\u003eextension\u003c/li\u003e\u003c/ul\u003eDon't bother searching for \"api\".\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-left:1em\"\u003e\u003cdiv /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3443725574767880072"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/how-the-extension-system-works/docs/how-to-update-the-release-notes"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/607117666182967889"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/607117666182967889"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/607117666182967889"}],"author":[{}],"sites$pageName":{"$t":"how-to-update-the-release-notes"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"YDspeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/36211457229797764"},"published":{"$t":"2013-03-14T13:01:11.539Z"},"updated":{"$t":"2014-07-23T18:36:48.313Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-23T18:36:47.246Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Test Code Labs"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/autotest-client-tests\"\u003eAutotest Client Tests\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/server-side-test\" /\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/server-side-test\" style\u003d\"font-size:10pt\"\u003eCodelab for server side test\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/dynamic-suite-codelab\"\u003eDynamic Suite Codelab\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/36211457229797764"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/36211457229797764"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/36211457229797764"}],"author":[{"name":{"$t":"Scott Zawalski"},"email":{"$t":"scottz@chromium.org"}}],"sites$pageName":{"$t":"test-code-labs"},"sites$revision":{"$t":"7"}},{"gd$etag":"\"Xil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8224657111052987757"},"published":{"$t":"2014-02-21T00:50:55.852Z"},"updated":{"$t":"2014-07-23T14:16:54.848Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-23T14:16:53.226Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"IDL build"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Steps\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eSteps\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-GYP\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eGYP\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Performance\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ePerformance\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Details\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eDetails\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Further-optimizations\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eFurther optimizations\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Cautions\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eCautions\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Rejected-optimizations\"\u003e\u003cstrong\u003e3.4 \u003c/strong\u003eRejected optimizations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Compile-multiple-files-in-a-single-process-in-sequence-or-via-multiprocessing-\"\u003e\u003cstrong\u003e3.4.1 \u003c/strong\u003eCompile multiple files in a single process (in sequence or via multiprocessing)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Fork-multiple-processes\"\u003e\u003cstrong\u003e3.4.2 \u003c/strong\u003eFork multiple processes\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Cache-IR\"\u003e\u003cstrong\u003e3.4.3 \u003c/strong\u003eCache IR\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Compute-public-dependencies-precisely\"\u003e\u003cstrong\u003e3.4.4 \u003c/strong\u003eCompute public dependencies precisely\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-References\"\u003e\u003cstrong\u003e3.5 \u003c/strong\u003eReferences\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe IDL build is a significant source of \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/generated-files\"\u003egenerated files\u003c/a\u003e, and a complex use of the build system (GYP or GN); see their documentation for possible issues.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Steps\" /\u003eSteps\u003c/h2\u003e\r\n\u003cdiv\u003e...\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-GYP\" /\u003eGYP\u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003eComponents other than bindings do not need to know about the internal organization of the bindings build. Currently the components \u003ccode\u003ecore\u003c/code\u003e and \u003ccode\u003emodules\u003c/code\u003e depend on \u003ccode\u003ebindings,\u003c/code\u003e specifically \u003ccode\u003ebindings_core\u003c/code\u003e (in \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/core/\"\u003ebindings/core\u003c/a\u003e) and \u003ccode\u003ebindings_modules\u003c/code\u003e (in \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/modules/\"\u003ebindings/modules\u003c/a\u003e), due to cyclic dependencies \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003ecore\u003c/code\u003e ⇄ \u003ccode\u003ebindings_core\u003c/code\u003e and \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003emodules\u003c/code\u003e ⇄ \u003ccode\u003ebindings_modules\u003c/code\u003e. These sh\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eould just include \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/core/core.gypi\"\u003ebindings/core/core.gypi\u003c/a\u003e or \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/modules/modules.gypi\"\u003ebindings/modules/modules.gypi\u003c/a\u003e, respectively, and depend on top-level targets, currently:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003ebindings/core/v8/generated.gyp:bindings_core_v8_generated\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003ebindings/modules/v8/generated.gyp:bindings_modules_v8_generated\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eGYP files (.gyp and .gypi) are arranged as follows:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cb\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cb\u003e.gyp:\u003c/b\u003e \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThere's a generated.gyp file in each directory that generates files (outputting to \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/out/Debug/gen/blink/bindings/\"\u003egen/blink/bindings\u003c/a\u003e/$dir\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e), namely core, core/v8, modules, and modules/v8; these correspond to global info (core and modules) and actual V8 bindings (core/v8 and modules/v8). There's also \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/scripts/scripts.gyp\"\u003escripts/scripts.gyp\u003c/a\u003e, for precaching in scripts (lexer/parser tables, compiling templates).\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e.gypi:\u003c/b\u003e The .gypi files are named (as usual) as:\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003efoo/foo.gypi        # main, public: list of static files and configuration variables\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003efoo/generated.gypi  # list of generated files\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003eThere is one bindings-specific complexity, namely idl.gypi\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e files (\u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/core/idl.gypi\"\u003ecore/idl.gypi\u003c/a\u003e and \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/bindings/modules/idl.gypi\"\u003emodules/idl.gypi\u003c/a\u003e), \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003edue to having to categorize the IDL files for the build (see \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"http://www.chromium.org/developers/web-idl-interfaces#TOC-Build\"\u003eWeb IDL interfaces: Build\u003c/a\u003e).\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThere are relatively long lists\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e of .gypi includes in the .gyp files, which are due to factoring for componentization, and are longer than desired due to \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003elayering violations, namely \u003ccode\u003ebindings_core\u003c/code\u003e → \u003ccode\u003ebindings_modules\u003c/code\u003e (Bug \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d358074\"\u003e358074\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e): \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003ethese make the (bad) dependencies explicit.\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Performance\" /\u003ePerformance\u003c/h2\u003e\r\n\u003cdiv\u003e\u003ci\u003eFor build performance in compiling a single IDL file, see \u003ca href\u003d\"http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Performance\"\u003eIDL compiler: Performance\u003c/a\u003e\u003c/i\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eBuild performance is one of the \u003c/span\u003e\u003ca href\u003d\"http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Goals\" style\u003d\"background-color:transparent;font-size:10pt\"\u003eIDL compiler goals\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e, though secondary to correctness and performance of the generated code.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe primary concern is minimizing \u003ci\u003efull build time\u003c/i\u003e (notably full bindings generation and compilation); the secondary concern is maximizing \u003ci\u003eincrementality\u003c/i\u003e of the build (only do full rebuilds when necessary). These priorities are because full builds are common (e.g., on build bots and for any compiler code changes), and changes to individual IDL files are also common, which should only rebuild that file's bindings and any dependents, not trigger a full rebuild.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eCurrent performance (as of Blink \u003ca href\u003d\"https://src.chromium.org/viewvc/blink?revision\u003d168630\"\u003er168630\u003c/a\u003e in March 2014) is acceptable: on a fast Linux workstation with 16 cores, full regeneration takes ~3 seconds (~50 seconds of user time, ~80 ms/IDL file), and full rebuilds on IDL changes only occur if a dependency IDL file (partial interface or implemented interface) is touched, which is infrequent.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe coarsest way to profile a full build – which is sufficient for verifying coarse improvements – is to do a build (using ninja), then \u003ccode\u003etouch idl_compiler.py\u003c/code\u003e and \u003ca href\u003d\"http://en.wikipedia.org/wiki/Time_(Unix)\" rel\u003d\"nofollow\"\u003e\u003ccode\u003etime(1)\u003c/code\u003e\u003c/a\u003e another build (most finely the targets should be \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003ccode\u003ebindings_core_v8_generated bindings_modules_v8_generated\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e but (for ninja) it's fine for the target to be \u003c/span\u003e\u003ccode style\u003d\"font-size:10pt;background-color:transparent\"\u003echrome\u003c/code\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e)\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e; \"user time\" is most relevant. This should only rebuild the bindings, but not recompile or do any other steps, like linking. Note that build system (like ninja) has some overhead, so you want to compare to an empty build, and that touching some other files may trigger other steps.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIn the overall build, bindings compilation and linking are more significant factors, but are difficult to improve: minimizing includes and minimizing and simplifying generated code are the main approaches.\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eThe main improvement would be precise computation of dependencies to minimize full rebuilds, so only dependent files are rebuild if a dependency is touched (Bug \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d341748\"\u003e341748\u003c/a\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e), but this would require GYP changes.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Details\" /\u003eDetails\u003c/h3\u003e\r\n\u003cdiv\u003eIDL build performance contains various components:\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ci\u003e(Preliminary):\u003c/i\u003e Build file generation (GYP runtime)\u003c/li\u003e\r\n\u003cli\u003eBuild system time (ninja runtime)\u003c/li\u003e\r\n\u003cli\u003eOverall IDL file recompile time (including auxiliary steps and parallelization)\u003c/li\u003e\r\n\u003cli\u003eIndividual IDL file compile time (bindings generation time, IDL → C++)\u003c/li\u003e\r\n\u003cli\u003eC++ compile time (bindings compile time, C++ → object code)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eBuild performance criteria of the IDL build are the time for the following tasks:\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eGenerate build files (gyp time)\u003c/li\u003e\r\n\u003cli\u003eRun build system (both empty build and overhead on regeneration or recompile)\u003c/li\u003e\r\n\u003cli\u003eGenerate all bindings\u003c/li\u003e\r\n\u003cli\u003eCompile all generated bindings\u003c/li\u003e\r\n\u003cli\u003eIncremental regeneration\u003c/li\u003e\r\n\u003cli\u003eIncremental recompile\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eThe key techniques to optimize these are:\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eGenerate build files: avoid computations in \u003ccode\u003e.gyp\u003c/code\u003e files, particularly \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e\u003csup\u003e2\u003c/sup\u003e) ones\u003c/li\u003e\r\n\u003cli\u003eRun build system: minimize size and complexity of generated build files (avoid excess dependencies)\u003c/li\u003e\r\n\u003cli\u003eGenerate all bindings: parallelize build, and optimize individual IDL compilation time\u003c/li\u003e\r\n\u003cli\u003eCompile all bindings: \u003cb\u003eFIXME ???\u003c/b\u003e \u003ci\u003e(minimize includes, shard aggregated bindings?)\u003c/i\u003e\u003c/li\u003e\r\n\u003cli\u003eIncremental regeneration: compute dependencies precisely (to avoid full regeneration)\u003c/li\u003e\r\n\u003cli\u003eIncremental recompile: \u003cb\u003eFIXME ???\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eCompilation of multiple IDL files is embarrassingly parallel, as files are almost completely independent (code generation is independent, and reading in is independent other than reading in implemented or referenced interfaces, which is currently minor, and global information, which is handled in a separate step). Thus with enough cores or a distributed build, compilation is very fast: assuming one core per IDL file, full recompile should take 0.1 seconds, plus distribution overhead.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Further-optimizations\" /\u003eFurther optimizations\u003c/h3\u003e\r\n\u003cdiv\u003eThe main areas at the overall build level that suggest further optimization are as follows. These would not help significantly with full rebuilds, but would improve incrementality. These are thus possible, but not high priorities.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ePrecise computation of dependencies, rather than conservative computation (Bug XXX)\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eThis would minimize full rebuilds, and decrease the size of generated build files: currently if a dependency IDL file (partial interface or implemented interface) is touched, \u003ci\u003eall\u003c/i\u003e bindings are regenerated (conservatively). Instead, precise computation of dependencies would mean only the dependent files are rebuilt, so 1 or 2 files instead of 600. Further, this would reduce the size of the generated build files, because instead of the conservative list of \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eabout 60 dependencies x 600 main IDL files \u003d 36,000 dependencies, this would have about 100 (some dependencies are implemented interfaces that are used multiple times); this would speed up build time due to lower overhead of reading and checking these dependencies.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eThis would require new features in GYP, to allow per-file dependency computation in rules.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eSplit global computations as individual compute public information steps and a consolidation step\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eThis would speed up incremental builds a bit, by minimizing the global computation, but may slow down full rebuilds significantly, due to launching \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e) processes.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eCurrently global computations are done in a single step, which processes all IDL files. Thus touching any IDL file requires reading all of them to recompute the global data. This could be replaced by a 2-step processes: compute the public data one file at a time (\u003ci\u003en\u003c/i\u003e processes), then have a consolidation step that reads these all in and produces the overall global data. Further, if the public data does not change (as is usually the case), the consolidation step need not run. \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eThis would thus speed up incremental builds. However, this would require \u003c/span\u003e\u003ci style\u003d\"background-color:transparent;font-size:10pt\"\u003en\u003c/i\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e additional processes, so it would slow down full rebuilds.\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Cautions\" /\u003eCautions\u003c/h3\u003e\r\n\u003cdiv\u003eCertain mistakes that significantly degrade build performance are easily made; all of these have either occurred or been proposed.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eTouching or regenerating global dependency targets\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eBe careful to use \"write only on diff\" (correctly) for all global dependency targets.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eTouching a global dependency\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e(a file or target that is a dependency of all IDL files) \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ecauses a full recompile: if a global dependency changes,\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e \u003c/span\u003e\u003ci style\u003d\"background-color:transparent;font-size:10pt\"\u003eall\u003c/i\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e IDL files must be recompiled. \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eGlobal dependency files are primarily the compiler itself, but also (for now) all dependency IDL files, since we compute dependencies conservatively in the build, not precisely. Global dependency targets (files generated in the preliminary steps) are primarily the global context, but also the generated global constructor IDL files, as these are partial interfaces (hence dependencies, hence treated as global dependencies). \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eTouching any IDL file requires recomputing the global context and these generated global files. \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eHowever, most changes to IDL files do not change the global dependencies (global context and global constructors), since they only change private information, and thus should not trigger full rebuilds. \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eThe \"write only on diff\" option, supported by some build systems, notably ninja, means that if these files do not change, we do not regenerate the targets, hence avoiding a full rebuild. If this is missed, touching any IDL file cause full regeneration.\u003c/span\u003e\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eExcess processes :: source of \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e) process overhead\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eAvoid launching processes per-IDL file: preferably only 1 process for the actual compilation, avoiding per-file caching steps.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eLaunching processes is relatively expensive, particularly on Windows. For global steps this is \u003ci\u003eO\u003c/i\u003e(1) in the number of IDL files, so adding an extra global build step is cheap, but for compiling individual IDL files this is \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e), so it's faster to have 1 process per IDL file, i.e., compile each file in a single step. Thus any changes that add a process per IDL file are expensive. These include: splitting global computations into \"compute per file one process at a time, then consolidate in one step\" (turns \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e) computation in 1 process into \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e) computation in \u003ci\u003en\u003c/i\u003e + 1 processes); splitting the compile into \"compute IR, then compile IR\" (turns \u003ci\u003en\u003c/i\u003e processes into 2\u003ci\u003en\u003c/i\u003e processes).\u003c/div\u003e\r\n\u003cul\u003e\u003cli\u003eDoing redundant work :: source of \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e\u003csup\u003e2\u003c/sup\u003e) algorithms\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eCompute global data in a single preliminary step.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nComputed data that is needed by more than one IDL file should generally be done a single time, most simply in the global context computation step (or a GYP variable); getting this wrong can turn \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e) work into O(\u003ci\u003en\u003c/i\u003e\u003csup\u003e2\u003c/sup\u003e) work. For example, public information about an interface should be computed once, rather than computing it every time it is used.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eHowever, in some cases redundant work is preferable to adding extra processes. For example, there is some redundancy in the front end, since some files (notably implemented interfaces) are read during the compile of several IDL files, but this is relatively rare (about \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e30/600\u003d5%\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e of files are read multiple times) and cheap (actual parsing is cheap relative to parser initialization), and fixing it would require a separate per-file caching step, which would increase the number of processes.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ci\u003eO\u003c/i\u003e(\u003ci\u003enk\u003c/i\u003e) and \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e\u003csup\u003e2\u003c/sup\u003e) work or data in build files\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eUse precise (not conservative) computations and static lists in GYP, and be careful of GYP rules.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eGYP rules generate actions; for the IDL build this is the \u003ccode\u003ebinding\u003c/code\u003e rule in the \u003ccode\u003eindividual_generated_bindings\u003c/code\u003e target, which generates one action per IDL file. Thus any work this does or data this generates is scaled by \u003ci\u003en\u003c/i\u003e. This is an issue for dependencies: the \u003ccode\u003einputs\u003c/code\u003e are used for all generated actions, and thus currently include all dependency files, which generates \u003ci\u003eO\u003c/i\u003e(\u003ci\u003enk\u003c/i\u003e) data (currently about 60 dependencies x 600 main IDL files \u003d 36,000 input lines in the actions, instead of ~100 (some dependencies are implemented interfaces that are used multiple times)), which slows down both gyp runtime and the build (ninja) runtime, as it needs to read and check all these dependencies. Further, any \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e) work in the inputs, notably calling a Python script that runs a global computation, results in \u003ci\u003eO\u003c/i\u003e(\u003ci\u003en\u003c/i\u003e\u003csup\u003e2\u003c/sup\u003e) work at gyp runtime.\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eSee also \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d350317\" style\u003d\"background-color:transparent;font-size:10pt\"\u003e350317\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e: Reduce size of individual_generated_bindings.ninja\u200b\u200b.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWork can be reduces to \u003ci\u003eO\u003c/i\u003e(1) if instead of using a Python script to compute dependencies dynamically (at gyp runtime), one determines the dependencies statically (when writing the \u003ccode\u003e.gyp, .gypi\u003c/code\u003e files). This is a key reason that there are multiple variables with lists of IDL files: this allows gyp to just expand the variables, rather than running a computation (and obviates the need for a separate Python script).\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Rejected-optimizations\" /\u003eRejected optimizations\u003c/h3\u003e\r\n\u003cdiv\u003eSome intuitively appealing optimizations don't actually work well or at all; these are discussed here. These generally have little impact (or negative impact) and involve significant complexity in the build or compiler.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Compile-multiple-files-in-a-single-process-in-sequence-or-via-multiprocessing-\" /\u003eCompile multiple files in a single process (in sequence or via multiprocessing)\u003c/h4\u003e\r\n\u003cdiv\u003ePython and library initialization can be further sped up by processing multiple IDL files in a single compiler run (a single compilation process). However, this significantly complicates the build due to needing to manually distribute the input files to various build steps, ideally one per available core. This interacts poorly with GYP (GYP rules are designed for a single input file and the corresponding output), and is only useful if you cannot fully distribute the build, and thus is not done.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNote that \u003ca href\u003d\"http://docs.python.org/2/library/multiprocessing.html\" rel\u003d\"nofollow\"\u003emultiprocessing\u003c/a\u003e or multithreading Python would not allow a single Python process to compile all files in parallel (thus minimizing initialization time), since the Python interpreter is not concurrency safe (hence not multithreaded; concretely this is due to the \u003ca href\u003d\"http://docs.python.org/2/glossary.html#term-global-interpreter-lock\" rel\u003d\"nofollow\"\u003eGlobal Interpreter Lock\u003c/a\u003e, GIL), and the actual parsing and templating are done in Python. A multiprocessing Python process could launch separate (OS) processes to compile individual files, but this offers no advantage over the build system doing it, and is more complex.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Fork-multiple-processes\" /\u003eFork multiple processes\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eOne could start a single Python process, which then forks others once it has initialized to reduce startup time (both of Python and of the libraries): either one per input file or distributing among them. This allows both parallelization and minimal initialization, so it would increase speed. However, this is platform dependent (\u003ccode\u003efork()\u003c/code\u003e is not available on Windows, and would need to be replaced by \u003ccode\u003espawn()\u003c/code\u003e or \u003ca href\u003d\"http://docs.python.org/2/library/subprocess.html\" rel\u003d\"nofollow\"\u003e\u003ccode\u003esubprocess\u003c/code\u003e\u003c/a\u003e), and would\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e move substantial build complexity into the compiler from the build system, hence avoided since this level of performance is not required.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Cache-IR\" /\u003eCache IR\u003c/h4\u003e\r\n\u003cdiv\u003eThe IR is computed multiple times for a few IDL files, namely implemented interfaces that are implemented by several IDL interfaces and targets of \u003ccode\u003e[PutForwards]\u003c/code\u003e. This is redundant work, so caching them would avoid this duplication. However, this would require splitting compilation into two steps – generate IR in one step, then compile IR in the second – and thus double the number of processes, which would slow down the build significantly, particularly on Windows. This can be worked around, at the expense of complicating the build, by only doing the caching for dependencies (or indeed only for implemented interfaces) and then checking for a cached IR file before reading the IDL file onself, but this is significant complexity for little benefit.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Compute-public-dependencies-precisely\" /\u003eCompute public dependencies precisely\u003c/h4\u003e\r\n\u003cdiv\u003eCurrently if the \u003ci\u003eglobal\u003c/i\u003e context changes, \u003ci\u003eall\u003c/i\u003e bindings are generated. This is conservative and simple, which is why we do it this way, but it causes excess full rebuilds: if the public data of one IDL file changes (e.g., its \u003ccode\u003e[ImplementedAs]\u003c/code\u003e), only bindings that actually depend on that public information (namely: use that interface) need to be rebuilt. Thus if IDL files depended on the public information of individual files, rather than on the global context, we could have more incremental rebuilds.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThis is not done because it would add significant complexity for little benefit (changes to public data are rare, and generally require a significant rebuild anyway), and \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ewould require GYP changes (above) for file-by-file dependency computation in rules.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-References\" /\u003eReferences\u003c/h3\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d341748\"\u003eIssue 341748: Improve bindings build\u003c/a\u003e: tracking bug for build rewrite (2014)\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/idl-build"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8224657111052987757"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8224657111052987757"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8224657111052987757"}],"author":[{"name":{"$t":"Nils Barth"},"email":{"$t":"nbarth@chromium.org"}}],"sites$pageName":{"$t":"idl-build"},"sites$revision":{"$t":"17"}},{"gd$etag":"\"YDspeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5654812728182475144"},"published":{"$t":"2012-01-12T18:23:16.060Z"},"updated":{"$t":"2014-07-18T17:34:26.379Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-07-18T17:34:22.738Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Core Principles"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Help-users-safely-navigate-the-web.\" /\u003eHelp users safely navigate the web.\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:13px\"\u003eEnsuring user safety means carefully balancing usability, capability and security. If we’re doing it right, these aspects should all work hand-in-hand. In most cases, we want security to be nearly invisible to the user. \u003c/span\u003e\u003cspan style\u003d\"font-size:13px\"\u003eWe update transparently and try to provide safe defaults without asking users to make security decisions. \u003c/span\u003eWhen \u003ca href\u003d\"http://support.google.com/chrome/bin/answer.py?hl\u003den\u0026amp;answer\u003d95617\"\u003esecurity indicators\u003c/a\u003e are surfaced,\u003cspan style\u003d\"font-size:13px\"\u003e we aim to clearly explain the situation and highlight the most important information, \u003c/span\u003e\u003cspan style\u003d\"font-size:13px\"\u003esuch as the hostname and SSL state in the address bar.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Design-for-defense-in-depth-and-more-depth-.\" /\u003eDesign for defense in depth (and more depth).\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eOur goal in designing Chrome’s security architecture was to layer defenses, and avoid single points of failure. Chrome’s sandbox architecture represents one of the most effective parts of this strategy, but it’s far from the only piece. We also employ the best available anti-exploit technologies—including \u003ca href\u003d\"http://en.wikipedia.org/wiki/Address_space_layout_randomization\" rel\u003d\"nofollow\"\u003eASLR\u003c/a\u003e, \u003ca href\u003d\"http://en.wikipedia.org/wiki/Data_Execution_Prevention\" rel\u003d\"nofollow\"\u003eDEP\u003c/a\u003e, \u003ca href\u003d\"http://www.matasano.com/research/Attacking_Clientside_JIT_Compilers_Paper.pdf#page\u003d24\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eJIT hardening\u003c/a\u003e, and \u003ca href\u003d\"http://msdn.microsoft.com/en-us/library/9a89h429.aspx\" rel\u003d\"nofollow\"\u003eSafeSEH\u003c/a\u003e—along with custom technologies like \u003ca href\u003d\"http://code.google.com/apis/safebrowsing/\"\u003eSafe Browsing\u003c/a\u003e, \u003ca href\u003d\"http://support.google.com/chrome/bin/answer.py?hl\u003den\u0026amp;answer\u003d1181003\"\u003eout-of-date plugin blocking\u003c/a\u003e, silent auto-update, and \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003everified boot\u003c/a\u003e on Chrome OS. And we continue to work towards advancing the state of the art with research into areas like per-origin sandboxing and control flow integrity.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Security-is-a-team-responsibility.\" /\u003eSecurity is a team responsibility.\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eThere’s a common misconception that security can be handled as a feature or add-on component. The fact is that security of any complex piece of software is a cross-cutting concern, determined by millions of seemingly innocuous decisions being made by developers every day. That’s why it’s essential for every team member to be aware of secure development practices, and work with their security team throughout the lifecycle of the project. This general awareness helps supplement our normal security review process of auditing, regression testing, and fuzzing.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Speed-matters.\" /\u003eSpeed matters.\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eUser safety depends on quickly turning around security issues, regardless of whether a vulnerability is discovered internally or reported by a third party. We are committed to promptly addressing all security issues, and delivering fixes to our users via our fast automatic update process. This approach has allowed us to maintain an \u003ca href\u003d\"http://www.accuvant.com/sites/default/files/images/webbrowserresearch_v1_0.pdf#page\u003d24\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eindustry-leading response time\u003c/a\u003e to security vulnerabilities—even when dealing with such a complex and politically charged issue as an irresponsible root Certificate Authority.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Be-transparent.\" /\u003eBe transparent.\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eWe do not downplay security impact or bury vulnerabilities with silent fixes, because doing so serves users poorly. Instead, we provide users and administrators with the information they need to accurately assess risk. We publicly document our \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/security-bug-lifecycle\"\u003esecurity handling proces\u003c/a\u003e\u003ca href\u003d\"http://dev.chromium.org/Home/chromium-security/security-bug-lifecycle\"\u003es\u003c/a\u003e, and we disclose all vulnerabilities fixed in Chrome and its dependencies—whether discovered internally or externally. Whenever possible, we list all fixed security issues in our \u003ca href\u003d\"http://googlechromereleases.blogspot.com/\" rel\u003d\"nofollow\"\u003erelease notes\u003c/a\u003e, and make the underlying details public as soon as other affected projects have an adequate amount of time to respond. When we do not control the disclosure timeline for a security issue and cannot list it at the time of release, we make the details of the issue public as soon as disclosure occurs.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Engage-the-community.\" /\u003eEngage the community.\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eNo software is perfect, and security bugs slip through even the best development and review processes. That’s why we’re grateful for the work of the independent security research community in helping us find and fix vulnerabilities. In response, we do our best to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/hall-of-fame\"\u003eacknowledge\u003c/a\u003e and \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/vulnerability-rewards-program\"\u003ereward\u003c/a\u003e their contributions by ensuring proper attribution, paying out bounties, and sponsoring security conferences. We leverage the community to even greater extent where we can, by hiring members directly onto our team and contracting with industry leading, independent security consultancies.\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Make-the-web-safer-for-everyone.\" /\u003eMake the web safer for everyone.\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eSecurity is not a zero-sum game. One browser does not succeed in security at the cost of others, and we’re all better off when the best security technologies and techniques are employed by everyone. To that end, we work closely with standards bodies and other browser makers to raise the bar by collaborating on various standards, including \u003ca href\u003d\"http://tools.ietf.org/html/draft-ietf-websec-key-pinning-01\" rel\u003d\"nofollow\"\u003epublic key pinning\u003c/a\u003e, \u003ca href\u003d\"http://www.w3.org/TR/CSP/\" rel\u003d\"nofollow\"\u003eContent Security Policies\u003c/a\u003e, and \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/spdy\"\u003eSPDY\u003c/a\u003e. We also open source or otherwise make our security technologies widely available (e.g. \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/nativeclient\"\u003eNative Client\u003c/a\u003e / Pepper, \u003ca href\u003d\"https://code.google.com/p/ots/\"\u003eOpen Type Sanitizer\u003c/a\u003e, \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/sandbox\"\u003eapplication sandboxing\u003c/a\u003e, and \u003ca href\u003d\"https://code.google.com/apis/safebrowsing/\"\u003eSafe Browsing\u003c/a\u003e).\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6743906577140407009"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/core-principles"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5654812728182475144"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5654812728182475144"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5654812728182475144"}],"author":[{"name":{"$t":"Justin Schuh"},"email":{"$t":"jschuh@chromium.org"}}],"sites$pageName":{"$t":"core-principles"},"sites$revision":{"$t":"7"}},{"gd$etag":"\"YDUpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6840003626758386297"},"published":{"$t":"2013-07-30T20:02:06.229Z"},"updated":{"$t":"2014-07-09T22:06:42.408Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-20T18:17:22.706Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Perf Keyvals"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003ch1 style\u003d\"text-align:left;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Note-perf-keyvals-described-in-this-page-has-been-deprecated.-If-your-test-output-perf-values-please-refer-to-http:-www.chromium.org-chromium-os-testing-perf-data\" /\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"font-size:15px;font-weight:normal;line-height:17.25px;white-space:pre-wrap\"\u003eNote perf keyvals described in this page has been deprecated. If your test output perf values, please refer to \u003c/span\u003e\u003c/font\u003e\u003ca dir\u003d\"ltr\" href\u003d\"http://www.chromium.org/chromium-os/testing/perf-data\" rel\u003d\"nofollow noreferrer\" style\u003d\"background-color:transparent;font-size:10pt;font-weight:normal;font-family:arial,sans-serif;line-height:16px\" target\u003d\"_blank\"\u003ehttp://www.chromium.org/chromium-os/testing/perf-data\u003c/a\u003e\u003c/font\u003e\u003c/h1\u003e\u003c/span\u003e\u003cspan\u003e\u003ch1 dir\u003d\"ltr\" style\u003d\"text-align:left;line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Currently-autotest-uses-a-special-kind-of-keyval-called-a-perf-keyval-to-store-performance-test-data.-A-perf-keyval----like-any-keyval-in-autotest----is-simply-a-key-value-pair-where-the-key-is-a-string-that-describes-the-value.-The-string-key-can-contain-\" /\u003e\u003cspan style\u003d\"font-weight:normal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eCurrently, autotest uses a special kind of keyval called a “perf keyval” to store performance test data.  A perf keyval -- like any keyval in autotest -- is simply a key/value pair, where the key is a string that describes the value. The string key can contain only letters, numbers, periods, dashes, and underscores, as defined in \u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-size:15px;font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_keyval\u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e() in \u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-size:15px;font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003echromeos/src/third_party/autotest/files/client/common_lib/base_utils.py\u003c/span\u003e\u003cspan style\u003d\"font-weight:normal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/h1\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ePerf keyvals are outputted by autotests via calls to \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_perf_keyval(DICT)\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, where \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDICT\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is a dictionary of perf key/value pairs.  There is no standardized format for how a chromeOS performance key string is specified. Unofficially, perf keys tend to follow the format “UNITS_DESCRIPTION”, as in “fps_WebGLAquarium”, but this format is not enforced by calls to \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_perf_keyval()\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Life-of-a-perf-keyval\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eLife of a perf keyval\u003c/span\u003e\u003c/h2\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eSummary\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e: a test outputs perf keyvals using \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_perf_keyval()\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, which are then pushed to output text files.  The autotest infrastructure then pulls these keyvals from the output files and dumps them into the results database when parsing server job results.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-From-a-test-to-output-file-s-\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFrom a test to output file(s)\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003edictionary of perf keyvals written by a test using “self.write_perf_keyval()”. \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;white-space:pre-wrap;line-height:1.15\"\u003eThat function is defined in: chromium-os/src/third_party/autotest/files/client/common_lib/test.py, in class base_test\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThat in turn passes the keyvals along to “write_iteration_keyval()”, defined in the same class\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_iteration_keyval() accepts a dictionary of “attr” type keyvals, and “perf” type keyvals.  It then calls utils.write_keyval() with each dictionary, passing along the “attr” and “perf” tags for each dictionary appropriately.  It then appends a newline to the “keyval” file in the current results directory.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_keyval() is defined in: chromium-os/src/third_party/autotest/files/client/common_lib/base_utils.py.  This function verifies that the keys in the keyval dictionary match an expected regex; then it writes the keyvals in sorted order to the keyval file in the specified directory (in “append” mode).\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ewrite_keyval() also accepts a tap_report object; if that is present and its “do_tap_report” attribute is true, then the keyvals are also passed to the tap_report’s “record_keyval()” function.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA tap_report object is associated with the job that a given test instance is a part of.  Hence, it’s referenced by write_perf_keyval() in class base_test as “self.job._tap”, which is initialized in file “chromium-os/src/third_party/autotest/files/client/common_lib/base_job.py” as a new TAPReport object.  class TAPReport is defined in the same file.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTAPReport is autotest’s support for generating TAP (\u003c/span\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/Test_Anything_Protocol\" style\u003d\"text-decoration:none\" rel\u003d\"nofollow\"\u003e\u003cspan style\u003d\"color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003eTest Anything Protocol\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e) report files.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-From-output-file-s-into-the-results-database\" /\u003e\u003cspan style\u003d\"font-family:Trebuchet MS;color:rgb(102,102,102);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eFrom output file(s) into the results database\u003c/span\u003e\u003c/h3\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAutotest’s TKO parser is what puts data into the results database\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eparse_test() in chromium-os/src/third_party/autotest/files/tko/models.py reads in the keyval file for a test and constructs a new models.test object from it.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eparse_test() is invoked by the state_iterator() function in chromium-os/src/third_party/autotest/files/tko/parsers/version_0.py (there’s also a version_1.py in there).  The files in this directory implement a state machine that parses/processes the results of an autotest job.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe state_iterator is driven by process_lines() and end() in chromium-os/src/third_party/autotest/files/tko/parsers/base.py.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eprocess_lines() is driven by _parse_status() in chromium-os/src/third_party/autotest/files/server/server_job.py\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhen _parse_status() calls process_lines(), it gets back information about new tests associated with the job.  It then calls __insert_test() with each of these tests, which then inserts the test results into the results database via a call to self.results_db.insert_test().\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e_parse_status() is invoked by the hook in class server_job_record_hook that implements the job.record hook for server job.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe record_hook is invoked in the record_entry() function in class status_logger in file chromium-os/src/third_party/autotest/files/client/common_lib/base_job.py.  That function is invoked whenever autotest needs to record a status_log_entry into the appropriate status log files.\u003cbr /\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Storage-of-perf-keyvals\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eStorage of perf keyvals\u003c/span\u003e\u003c/h2\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003e“keyval” files\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e: Perf keyvals are initially written into an output file named \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ekeyval\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e that is contained within the \u003c/span\u003e\u003cspan style\u003d\"font-family:Courier New;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eresults\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e output folder of an autotest run.  Each perf keyval is printed on a separate line in this file.  An example is:\u003cbr /\u003e\u003cbr /\u003eFPS_FlashGaming{perf}\u003d17.349133\u003cbr /\u003e\u003cbr /\u003eThe format of each line is PERF_KEY_STRING{perf}\u003dPERF_VALUE.  The “{perf}” is just a tag indicating that the keyval is a performance keyval.  Autotests can also run for multiple iterations.  When that happens, results for all iterations are printed inside the same (single) keyval file, with a blank line separating the perf keyvals from each iteration.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eautotest results database\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e: perf keyvals are also extracted from the keyval output files by autotest’s TKO parser, and are then dumped into the autotest results database.  The perf keyvals are stored in a table named “tko_iteration_result”, with fields “attribute” (the perf key) and “value” (the perf value).  Each entry in that table is associated with a unique test run index, in field “test_idx”.  There is a view in the autotest results database called “tko_perf_view_2” that simplifies querying for the perf keyvals associated with a test run.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:10pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Consumers-of-perf-keyvals\" /\u003e\u003cspan style\u003d\"font-size:17px;font-family:Trebuchet MS;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eConsumers of perf keyvals\u003c/span\u003e\u003c/h2\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eConsumers of perf keyval files\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAutotest TKO parser (to get the keyvals into the results database)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eteam members who are manually inspecting the results of performance test runs\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eConsumers of perf keyvals in the autotest results database\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003ePerformance dashboard: automatically extracts new perf keyvals daily at 3am\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3740145594917216428"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/autotest-keyvals/perf-keyvals"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6840003626758386297"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6840003626758386297"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6840003626758386297"}],"author":[{}],"sites$pageName":{"$t":"perf-keyvals"},"sites$revision":{"$t":"9"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7747808275369718459"},"published":{"$t":"2014-06-29T14:11:46.596Z"},"updated":{"$t":"2014-06-29T14:11:46.615Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-29T14:11:46.596Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"suspend_flowchart.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7747808275369718459"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4637016293833556964"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/power_manager/suspend-and-resume/suspend_flowchart.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7747808275369718459"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7747808275369718459"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7747808275369718459"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7747808275369718459"}],"author":[{"name":{"$t":"Dan Erat"},"email":{"$t":"derat@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3599293551224553411"},"published":{"$t":"2014-06-27T14:57:19.474Z"},"updated":{"$t":"2014-06-27T14:57:19.503Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-27T14:57:19.474Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"sunburst.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3599293551224553411"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/sunburst.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3599293551224553411"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3599293551224553411"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3599293551224553411"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3599293551224553411"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8005308679676144038"},"published":{"$t":"2014-06-26T16:42:14.591Z"},"updated":{"$t":"2014-06-26T22:20:35.322Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-26T22:20:33.970Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"C++ exception support"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv\u003eC++ exceptions are disabled by default for all C and C++ code. If you need them, you can white-list your ebuild.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eBackground\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003eC++ exceptions are not allowed by the \u003c/span\u003e\u003ca href\u003d\"http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml\" style\u003d\"color:rgb(17,85,204);font-family:arial;font-size:small\"\u003eGoogle C++ Style Guide\u003c/a\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e and only a few projects use them. This supports adds a some overhead to the binary file on the .eh_frame and .eh_frame_hdr sections, even if you don't use try/catch/throw, even if your program is in C. Nevertheless, they are enabled by default by the compiler, since some exception support is required even if you don't use them. For example, if function f() calls g() calls h(), and h() throws an exception that f() is supposed to catch, then g() also needs to be compiled with exception support, even if g() is a C function.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003eThe overhead is in the range of 5% to 10% of the binary size, depending of the average size of your functions, so we disable it by default.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb style\u003d\"font-size:medium;color:rgb(34,34,34);font-family:arial;background-color:transparent\"\u003eWhat to white-list\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf your application uses try, catch or throw, it needs to be withe-listed because otherwise it won't compile.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf your application calls a library that might throw an exception, but you don't catch it, the application doesn't need to be compiled with exceptions support. If the library throws an exception, the application will be terminated in either case.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf your application catches an exception that is thrown by a function called by an intermediate library, the library also needs to be compiled with exceptions support. For example, if you pass a callback to a library that might throw an exception, then the library should be also compiled with exception support. That's why glib and glibc are white-listed.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial\"\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eImplementation\u003c/b\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo disable the exception support, we pass \u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003e\"-fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables\" in CFLAGS and CXXFLAGS by default. To white-list them, we filter these flags from CFLAGS and CXXFLAGS. We also define the environment variable CXXEXCEPTIONS to 0 or 1 to determine whether the exceptions are enabled.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003eThe flags are added on the \u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-size:small;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromiumos-overlay/chromeos/make.conf.*-target\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003e files. To re-enable this support, you can call the bash function \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\" size\u003d\"2\"\u003ecros_enable_cxx_exceptions\u003c/font\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial\" size\u003d\"2\"\u003e defined in \u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-size:small;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003echromiumos-overlay/profiles/base/profile.bashrc\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003e. That function will filter out the flags from CXXFLAGS and CFLAGS.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003eThis can be done on a per ebuild basis. For example, the dev-libs/dbus-c++ ebuild has the following snippet on \u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:courier new,monospace;font-size:small;background-color:transparent\"\u003echromiumos-overlay/chromeos/config/env/dev-libs/dbus-c++\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-size:small;background-color:transparent\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e.\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\" size\u003d\"2\"\u003e\u003cdiv\u003ecros_pre_src_prepare_enable_cxx_exceptions() {\u003c/div\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\" size\u003d\"2\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"white-space:pre\"\u003e\t\u003c/span\u003ecros_enable_cxx_exceptions\u003c/div\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont color\u003d\"#222222\" face\u003d\"courier new, monospace\" size\u003d\"2\"\u003e\u003cdiv\u003e}\u003c/div\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8945126227284375934"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/build/c-exception-support"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8005308679676144038"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8005308679676144038"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8005308679676144038"}],"author":[{"name":{"$t":"Alex Deymo"},"email":{"$t":"deymo@chromium.org"}}],"sites$pageName":{"$t":"c-exception-support"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"USl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1685046760441667498"},"published":{"$t":"2009-12-11T04:25:59.733Z"},"updated":{"$t":"2014-06-26T16:45:19.627Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-11-02T21:35:25.741Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Git Troubleshooting"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-My-pull-is-failing\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eMy pull is failing\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-My-push-was-rejected\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eMy push was rejected\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-I-can-t-gclient-sync\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eI can't gclient sync\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Missing-dependency\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eMissing dependency\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-My-pull-is-failing\" /\u003eMy pull is failing\u003c/h3\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003eIf you get an error like this:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  ssh: connect to host gitrw.chromium.org port 9223: Connection refused\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003essh is failing to connect for some reason.  (In the above example, I had the port wrong.)  Verify your ssh configuration is correct -- that you have the keys set up, that you have right hostname and port, etc. depending on the error message.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you get an error like this when pulling:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  ERROR:gitosis.serve.main:Repository read access denied\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003eThe \"gitosis\" in the error message indicates you've successfully sshed to the server, but that something has gone wrong after that.  Verify the path to the git repository you're trying to pull is correct with something like\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  git config remote.origin.url\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-My-push-was-rejected\" /\u003eMy push was rejected\u003c/h3\u003eIf the output of git-cl looks like this:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003e$ git cl push\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003eDescription: 'Clean up to move NewStringCopy from util to chromeos/string.\\n\\nReview URL: \u003c/code\u003e\u003ca href\u003d\"http://codereview.chromium.org/460001\" target\u003d\"_blank\"\u003e\u003ccode\u003ehttp://codereview.chromium.\u003c/code\u003e\u003ccode\u003eorg/460001\u003c/code\u003e\u003c/a\u003e\u003ccode\u003e'\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003e .gitignore                    |    8 +++++++-\u003c/code\u003e\u003c/div\u003e\u003ccode\u003e1 file changed, 7 insertions(+), 1 deletion(-)\u003c/code\u003e\u003cdiv\u003e\u003ccode\u003eAbout to commit; enter to confirm.\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\r\nTo ssh://gitrw.chromium.org/\u003c/code\u003e\u003ccode\u003echromiumos\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e ! [rejected]        HEAD -\u0026gt; master (non-fast forward)\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eerror: failed to push some refs to 'ssh://gitrw.chromium.org/\u003c/code\u003e\u003ccode\u003echromiumos'\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003eYour branch is out of date. You need to run:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ gclient sync\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e$ git cl push\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-I-can-t-gclient-sync\" /\u003eI can't gclient sync\u003cbr /\u003e\u003c/h3\u003eIf gclient sync is outputting something like this:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ gclient sync\u003c/code\u003e\u003cspan\u003e\u003cbr /\u003e\u003ccode\u003e        Already in a conflict, i.e. (no branch).\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e        Fix the conflict and run gclient again.\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e        Or to abort run:\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e                git-rebase --abort\u003c/code\u003e\u003cbr /\u003e\u003ccode\u003e        See man git-rebase for details.\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cbr /\u003eYou are inside a rebase conflict. You can either fix the conflict:\u003cbr /\u003e\u003cbr /\u003e\u003ca href\u003d\"http://www.neeraj.name/blog/articles/811-how-to-resolve-git-merge-conflict-caused-while-doing-git-rebase\" rel\u003d\"nofollow\"\u003ehttp://www.neeraj.name/blog/articles/811-how-to-resolve-git-merge-conflict-caused-while-doing-git-rebase\u003c/a\u003e\u003cbr /\u003e\u003cbr /\u003eOr undo the rebase:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ git rebase --abort\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Missing-dependency\" /\u003eMissing dependency\u003cbr /\u003e\u003c/h3\u003eIf \u003cb\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003esetup_board\u003c/span\u003e\u003c/b\u003e is failing with output something like this:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u0026gt;\u0026gt;\u0026gt; Failed to emerge chromeos-base/kernel-headers-0.0.1 for /build/XXX/, Log file:\u003cbr /\u003e\u0026gt;\u0026gt;\u0026gt;  '/build/XXX/tmp/portage/chromeos-base/kernel-headers-0.0.1/temp/build.log'\u003cbr /\u003e * Using kernel files: trunk/src/third_party/kernel-XXX\u003cbr /\u003ecp: cannot stat `trunk/src/third_party/kernel-XXX/*': No such file or directory\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003eYou might be missing extra components, and need to add them to your \u003cb\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e.gclient\u003c/span\u003e\u003c/b\u003e file so that it contains a custom_deps clause something like:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e    \"custom_deps\" : {\u003cbr /\u003e      # To use the trunk of a component instead of what's in DEPS:\u003cbr /\u003e      #\"component\": \"https://svnserver/component/trunk/\",\u003cbr /\u003e      # To exclude a component from your working copy:\u003cbr /\u003e      #\"data/really_large_component\": None,\u003cbr /\u003e      \"chromeos/src/third_party/kernel-XXX\": \"ssh://chromiumos-git/kernel-XXX.git\"\u003cbr /\u003e    },\u003cbr /\u003e\r\n\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nwhere the LHS is the location in your source tree relative to the config file, and the RHS is a valid git URL.  After fixing up the config file, a \u003cb\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003egclient sync\u003c/span\u003e\u003c/b\u003e should fetch the missing bits.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/git-troubleshooting"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1685046760441667498"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1685046760441667498"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1685046760441667498"}],"author":[{}],"sites$pageName":{"$t":"git-troubleshooting"},"sites$revision":{"$t":"18"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5733861215638390268"},"published":{"$t":"2014-06-20T18:02:19.174Z"},"updated":{"$t":"2014-06-20T18:02:19.202Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T18:02:19.174Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stumpy-bottom-bare.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5733861215638390268"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-bottom-bare.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5733861215638390268"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5733861215638390268"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5733861215638390268"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5733861215638390268"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8516548610399865924"},"published":{"$t":"2014-06-20T18:02:06.164Z"},"updated":{"$t":"2014-06-20T18:02:06.189Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T18:02:06.164Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stumpy-bottom-cards.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8516548610399865924"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-bottom-cards.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8516548610399865924"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8516548610399865924"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8516548610399865924"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8516548610399865924"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3030080875452812698"},"published":{"$t":"2014-06-20T18:01:47.623Z"},"updated":{"$t":"2014-06-20T18:01:47.654Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T18:01:47.623Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stumpy-top-bare.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3030080875452812698"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-bare.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3030080875452812698"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3030080875452812698"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3030080875452812698"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3030080875452812698"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8176029382327786592"},"published":{"$t":"2014-06-20T18:01:34.729Z"},"updated":{"$t":"2014-06-20T18:01:34.752Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T18:01:34.729Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stumpy-top-mid.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8176029382327786592"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-mid.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8176029382327786592"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8176029382327786592"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8176029382327786592"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8176029382327786592"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/29978284204520062"},"published":{"$t":"2014-06-20T18:01:20.650Z"},"updated":{"$t":"2014-06-20T18:01:20.677Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T18:01:20.650Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stumpy-top-full.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/29978284204520062"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/stumpy-top-full.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/29978284204520062"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/29978284204520062"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/29978284204520062"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/29978284204520062"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6545612248197432419"},"published":{"$t":"2014-06-20T01:01:54.344Z"},"updated":{"$t":"2014-06-20T01:01:54.368Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T01:01:54.344Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Plugin-blocked-yellow-slide.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6545612248197432419"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4927629288120429199"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/npapi-deprecation/Plugin-blocked-yellow-slide.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6545612248197432419"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6545612248197432419"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6545612248197432419"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6545612248197432419"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3776869653993540484"},"published":{"$t":"2014-06-20T01:01:07.640Z"},"updated":{"$t":"2014-06-20T01:01:07.666Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T01:01:07.640Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Plugin-blocked yellow slide and bubble.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3776869653993540484"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4927629288120429199"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/npapi-deprecation/Plugin-blocked%20yellow%20slide%20and%20bubble.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3776869653993540484"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3776869653993540484"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3776869653993540484"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3776869653993540484"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3589469770777762210"},"published":{"$t":"2014-06-20T01:00:37.292Z"},"updated":{"$t":"2014-06-20T01:00:37.316Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-20T01:00:37.292Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Plugin-blocked bubble.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3589469770777762210"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4927629288120429199"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/npapi-deprecation/Plugin-blocked%20bubble.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3589469770777762210"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3589469770777762210"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3589469770777762210"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3589469770777762210"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"XSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7680873033739567159"},"published":{"$t":"2014-06-19T21:50:46.388Z"},"updated":{"$t":"2014-06-19T22:29:03.332Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-19T22:29:01.951Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Userland Boot in Chrome OS"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1 sites-layout-empty-tile\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/userland-boot"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7680873033739567159"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7680873033739567159"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7680873033739567159"}],"author":[{"name":{"$t":"Richard Barnette"},"email":{"$t":"jrbarnette@chromium.org"}}],"sites$pageName":{"$t":"userland-boot"},"sites$revision":{"$t":"14"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3400883890219767524"},"published":{"$t":"2014-06-12T21:25:06.987Z"},"updated":{"$t":"2014-06-12T21:25:07.019Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-12T21:25:06.987Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Selection_459.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3400883890219767524"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3997645127893838801"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/dell-chromebook-11/Selection_459.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3400883890219767524"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3400883890219767524"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3400883890219767524"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3400883890219767524"}],"author":[{"name":{"$t":"Jean Zheng"},"email":{"$t":"jean@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6409181229743304185"},"published":{"$t":"2014-06-11T17:53:39.904Z"},"updated":{"$t":"2014-06-12T00:14:06.353Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-12T00:14:05.287Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Developer Shell Access"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Goals\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eGoals\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Summary\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eSummary\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Buildtime\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eBuildtime\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Runtime\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eRuntime\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode-Disabled\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eDeveloper Mode Disabled\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-VT-Switching\"\u003e\u003cstrong\u003e5.1.1 \u003c/strong\u003eVT Switching\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Sysrq-Magic-Key\"\u003e\u003cstrong\u003e5.1.2 \u003c/strong\u003eSysrq Magic Key\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Crosh-Shell\"\u003e\u003cstrong\u003e5.1.3 \u003c/strong\u003eCrosh Shell\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-SSH\"\u003e\u003cstrong\u003e5.1.4 \u003c/strong\u003eSSH\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-sudo-su\"\u003e\u003cstrong\u003e5.1.5 \u003c/strong\u003esudo/su\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-pam\"\u003e\u003cstrong\u003e5.1.6 \u003c/strong\u003epam\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-groups\"\u003e\u003cstrong\u003e5.1.7 \u003c/strong\u003egroups\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-passwords\"\u003e\u003cstrong\u003e5.1.8 \u003c/strong\u003epasswords\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-Mode-Enabled\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003eDeveloper Mode Enabled\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-VT-Switching1\"\u003e\u003cstrong\u003e5.2.1 \u003c/strong\u003eVT Switching\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Sysrq-Magic-Key1\"\u003e\u003cstrong\u003e5.2.2 \u003c/strong\u003eSysrq Magic Key\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Crosh-Shell1\"\u003e\u003cstrong\u003e5.2.3 \u003c/strong\u003eCrosh Shell\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-SSH1\"\u003e\u003cstrong\u003e5.2.4 \u003c/strong\u003eSSH\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-sudo-su1\"\u003e\u003cstrong\u003e5.2.5 \u003c/strong\u003esudo/su\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-pam1\"\u003e\u003cstrong\u003e5.2.6 \u003c/strong\u003epam\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-groups1\"\u003e\u003cstrong\u003e5.2.7 \u003c/strong\u003egroups\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-passwords1\"\u003e\u003cstrong\u003e5.2.8 \u003c/strong\u003epasswords\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-References\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eReferences\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eDevelopers often need shell access to their Chromium OS device in order to sanely debug things in the system. Think opening crosh and typing \"shell\", and then logging in as root with \"sudo\". Or logging into a VT console when the UI is broken. Or logging in remotely via ssh.\u003c/p\u003e\r\n\u003cp\u003eHowever, this system is at odds with providing a simple system that is as secure as possible, so we need to analyze the trade offs.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Goals\" /\u003eGoals\u003c/h2\u003e\r\n\u003cul\u003e\u003cli\u003eSecurity should not be impacted when developer mode is turned off,\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eboth directly -- e.g. user sitting in front of the machine,\u003c/li\u003e\r\n\u003cli\u003eor indirectly -- e.g. an exploit that manages to execute programs outside of the browser as the same user.\u003c/li\u003e\r\n\u003cli\u003eThis means no shell, ssh, VT, etc... access.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eThe system should be dynamic.\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eTake a normal verified/secure image, put it into developer mode, and shell access will start working.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003ePasswords/ssh keys cannot be static at build time in release images.\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eUsers may opt to set their own passwords in their own personal builds.\u003c/li\u003e\r\n\u003cli\u003eTest images may include preset authentication (discussion of this is ongoing, but out of scope of this doc).\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eUsers can enable password protection on the fly.\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eKeeps people from sitting down, getting a shell, and then running sudo on your system.\u003c/li\u003e\r\n\u003cli\u003ePasswords protect all avenues of access equally.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h2\u003e\r\n\u003cp\u003eTODO(vapier)\r\n\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Buildtime\" /\u003eBuildtime\u003c/h2\u003e\r\n\u003cp\u003eTODO(vapier)\r\n\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Runtime\" /\u003eRuntime\u003c/h2\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-Mode-Disabled\" /\u003eDeveloper Mode Disabled\u003c/h3\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-VT-Switching\" /\u003eVT Switching\u003c/h4\u003e\r\n\u003cdiv\u003eWhen X is launched by the session manager, it is passed the -maxvt flag set to 0. This way X itself ignores the key combos.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Sysrq-Magic-Key\" /\u003eSysrq Magic Key\u003c/h4\u003e\r\n\u003cp\u003eThe hotkey-access.conf script will turn off all sysrq requests except for the \"x\" key by updating \u003ccode\u003e/proc/sys/kernel/sysrq\u003c/code\u003e.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Crosh-Shell\" /\u003eCrosh Shell\u003c/h4\u003e\r\n\u003cp\u003eThe crosh script is still available, but it does not allow access to the \"shell\" command (among others).\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-SSH\" /\u003eSSH\u003c/h4\u003e\r\n\u003cp\u003eThe ssh sever is not included in the base image, so it will never autostart. If it was started somehow, then the sections below apply (which is to say, it still wouldn't allow logins).\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-sudo-su\" /\u003esudo/su\u003c/h4\u003e\r\n\u003cp\u003eThese cannot be run directly (as no shell is available), but even then, access is denied via pam.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-pam\" /\u003epam\u003c/h4\u003e\r\n\u003cp\u003eA custom pam stack (\"chromeos-auth\") is installed that handles authentication for the \"login\" and \"sudo\" services. When developer mode is disabled, this stack will skip itself and continue to the normal system stacks.\u003c/p\u003e\r\n\u003cp\u003eFor more details on pam, see \u003ca href\u003d\"http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html\" rel\u003d\"nofollow\"\u003eThe Linux-PAM System Administrators' Guide\u003c/a\u003e.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-groups\" /\u003egroups\u003c/h4\u003e\r\n\u003cp\u003eThe chronos account is not part of the admin groups that would implicitly grant access (e.g. \u003ccode\u003ewheel\u003c/code\u003e).\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-passwords\" /\u003epasswords\u003c/h4\u003e\r\n\u003cp\u003eThe system password database (/etc/shaddow) is in the read-only rootfs and cannot be modified. The default images will list accounts with passwords set to \"*\" (so that password authentication will fail).\u003c/p\u003e\r\n\u003cp\u003eThe user custom dev mode password is not checked at all (see the pam section above).\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-Mode-Enabled\" /\u003eDeveloper Mode Enabled\u003c/h3\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-VT-Switching1\" /\u003eVT Switching\u003c/h4\u003e\r\n\u003cdiv\u003eWhen X is launched by the session manager, it is passed the -maxvt flag set to 2. This allows access to the VT2 console. Access is controlled by pam.\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Sysrq-Magic-Key1\" /\u003eSysrq Magic Key\u003c/h4\u003e\r\n\u003cp\u003eThe hotkey-access.conf script will enable all sysrq requests.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Crosh-Shell1\" /\u003eCrosh Shell\u003c/h4\u003e\r\n\u003cp\u003eThe crosh script allows access to the \"shell\" command (among others).\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-SSH1\" /\u003eSSH\u003c/h4\u003e\r\n\u003cp\u003eIf it is launched by hand, or using a test image that autolaunches it, access is controlled by the sections below.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-sudo-su1\" /\u003esudo/su\u003c/h4\u003e\r\n\u003cp\u003eAccess is controlled by pam.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-pam1\" /\u003epam\u003c/h4\u003e\r\n\u003cp\u003eA custom pam stack (\"chromeos-auth\") is installed that handles authentication for the \"login\" and \"sudo\" services. When developer mode is enabled, this stack will:\u003c/p\u003e\r\n\r\n\u003cul\u003e\u003cli\u003eIf a custom devmode password is set\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThat password is allowed for authentication\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eIf a custom devmode password is not set\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIf the account is in /etc/shadow\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eAccess is not allowed\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eIf the account is in /etc/shadow but no password set yet\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003ePasswordless access is granted\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eIf the account is in /etc/shadow with a password set\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eAccess is not allowed\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003cp\u003eNote that this only applies to this particular stack. Other pam stacks may allow/deny independently.\u003c/p\u003e\r\n\r\n\u003cp\u003eFor more details on pam, see \u003ca href\u003d\"http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html\" rel\u003d\"nofollow\"\u003eThe Linux-PAM System Administrators' Guide\u003c/a\u003e.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-groups1\" /\u003egroups\u003c/h4\u003e\r\n\u003cp\u003eThe chronos account is not part of the admin groups that would implicitly grant access (e.g. \u003ccode\u003ewheel\u003c/code\u003e).\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-passwords1\" /\u003epasswords\u003c/h4\u003e\r\n\u003cp\u003eThe system password database (/etc/shaddow) is in the read-only rootfs and cannot be modified. The default images will list accounts with passwords set to \"*\" (so that password authentication will fail).\u003c/p\u003e\r\n\u003cp\u003eThe user may set a custom password at runtime with the \u003ccode\u003echromeos-setdevpasswd\u003c/code\u003e script which is checked by pam.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-References\" /\u003eReferences\u003c/h2\u003e\r\n\r\n\u003cul\u003e\u003cli\u003ehttp://crbug.com/182572\u003c/li\u003e\r\n\u003cli\u003ehttp://crbug.com/217710\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/developer-shell-access"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6409181229743304185"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6409181229743304185"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6409181229743304185"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"developer-shell-access"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"Xyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/298205378256273737"},"published":{"$t":"2013-03-05T01:14:47.813Z"},"updated":{"$t":"2014-06-10T09:19:43.068Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-10T09:19:40.920Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chromium Clobber Landmines"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-are-they-\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eWhat are they?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-do-I-use-them-\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eHow do I use them?\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Example:\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eExample:\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Frequently-Asked-Questions:\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eFrequently Asked Questions:\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Details-please...\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eDetails, please...\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Use-cases\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eUse cases\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Moving-generated-files\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eMoving generated files\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-are-they-\" /\u003eWhat are they?\u003c/h2\u003e\r\n\u003cdiv\u003eClobber landmines are an easy way to send a targeted clobber to a class of builder machines (i.e. bot machines on build.chromium.org). This can be useful in the following circumstances:\u003c/div\u003e\r\n\r\n\u003cul\u003e\u003cli\u003eA build breakage is discovered and requires all the bots for a given operating system to clobber\u003c/li\u003e\r\n\u003cli\u003eYou know you're making a change which will introduce binary incompatibility\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eLandmines have the property that if a bot 'rolls over' the revision containing them (either forwards or backwards), it will trigger a clobber. This is quite useful for trybots which can be assigned random base revisions, or may even just switch between HEAD and LKGR multiple times per day. Simply clobbering the bot manually once may not be enough to make sure that it's 'fixed' for good.\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-do-I-use-them-\" /\u003eHow do I use them?\u003c/h2\u003e\r\n\u003cdiv\u003eSimply add logic to \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/build/get_landmines.py\"\u003e\u003ccode\u003ebuild/get_landmines.py\u003c/code\u003e\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e in the \u003ca href\u003d\"https://code.google.com/p/chromium/codesearch#chromium/src/build/get_landmines.py\u0026amp;q\u003dprint_landmines\"\u003e\u003ccode\u003eprint_landmines\u003c/code\u003e\u003c/a\u003e\u003ccode\u003e()\u003c/code\u003e function. There are a variety of parameters which you can use to fine-tune the effect of a landmine:\u003c/span\u003e\u003c/div\u003e\r\n\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-color:rgb(136,136,136);border-width:1px\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:199px;height:14px\"\u003e\r\n \u003cb\u003eLandmine parameter/function\u003c/b\u003e\r\n\u003c/td\u003e\r\n\u003ctd style\u003d\"width:213px;height:14px\"\u003e \u003cb\u003eExample values\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"width:369px;height:14px\"\u003e \u003cb\u003eDescription\u003c/b\u003e\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:199px;height:14px\"\u003e platform()\u003c/td\u003e\r\n\u003ctd style\u003d\"width:213px;height:14px\"\u003e 'win', 'mac', 'linux', 'ios', or 'android'\r\n\u003c/td\u003e\r\n\u003ctd style\u003d\"width:369px;height:14px\"\u003e target platform being built.\u003c/td\u003e\r\n\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:199px;height:14px\"\u003e gyp_defines()\u003c/td\u003e\r\n\u003ctd style\u003d\"width:213px;height:14px\"\u003e {'component': 'static_library'} ...\u003c/td\u003e\r\n\u003ctd style\u003d\"width:369px;height:14px\"\u003e dict()-ification of the GYP_DEFINES env var.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:199px;height:14px\"\u003e distributor()\u003cspan\u003e    \u003c/span\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"width:213px;height:14px\"\u003e 'goma', 'ib', or None\u003c/td\u003e\r\n\u003ctd style\u003d\"width:369px;height:14px\"\u003e the distributed compile technology in use for this build.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:199px;height:14px\"\u003e builder()\u003c/td\u003e\r\n\u003ctd style\u003d\"width:213px;height:14px\"\u003e 'make', 'ninja', 'xcode', or 'msvs'\u003c/td\u003e\r\n\u003ctd style\u003d\"width:369px;height:14px\"\u003e the builder technology for this build. \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:199px;height:14px\"\u003e target\u003c/td\u003e\r\n\u003ctd style\u003d\"width:213px;height:14px\"\u003e 'Release', 'Debug'\u003c/td\u003e\r\n\u003ctd style\u003d\"width:369px;height:14px\"\u003e the target that print_landmines() is generating landmines for.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003eTo add a landmine for the given configuration, just \u003ccode\u003eadd()\u003c/code\u003e a message in \u003ccode\u003eprint_landmines()\u003c/code\u003e, conditioned on the configuration. Try to make the reason for the landmine as descriptive as possible, citing relevant revisions, CLs or bugs.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Example:\" /\u003eExample:\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;font-size:10pt\"\u003edef print_landmines(target):\u003cbr /\u003e\r\n  # ... Other landmines here\u003cbr /\u003e\r\n\u003c/span\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e  \u003c/font\u003e\u003cfont style\u003d\"line-height:1;font-size:10pt\"\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003eif platform() \u003d\u003d 'win' and builder() \u003d\u003d 'ninja':\u003c/font\u003e\u003cbr /\u003e\r\n\u003c/font\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;line-height:1;font-size:10pt\"\u003e    add('Compile on cc_unittests fails due to symbols removed in r185063.')\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Frequently-Asked-Questions:\" /\u003eFrequently Asked Questions:\u003c/h2\u003e\r\n\u003cdiv\u003e\u003cb\u003eQ: What happens if I delete/clean up/replace landmines in get_landmines()?\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eA: This is OK (as in, it won't break anything), but note that it will cause bots which match the configuration of the removed landmines to clobber again. \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSometimes this is done intentionally: if there's a frequently-clobbered configuration it may be expedient to only have one landmine which is replaced when a clobber is needed.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eQ: Can I include a landmine in a CL which does other things?\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eA: If you know that your change will \u003cb\u003edefinitely\u003c/b\u003e require some bots to clobber, then yes, you SHOULD include it with the rest of the changes.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eQ: How do I include a landmine for a change in a different repository (e.g., Blink, Skia)\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003eA: The change to \u003ccode\u003ebuild/get_landmines.py\u003c/code\u003e should be included in the \u003ca href\u003d\"http://dev.chromium.org/developers/how-tos/get-the-code#Rolling_DEPS\"\u003eroll\u003c/a\u003e (i.e., the CL that changes DEPS to update the revision). You will need to contact the current \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs#TOC-What-is-a-gardener-\"\u003egardener\u003c/a\u003e of your component (listed at the top left of the \u003ca href\u003d\"http://build.chromium.org/p/chromium/waterfall?reload\u003d120\"\u003eBuildBot waterfall\u003c/a\u003e) and have them apply the change in their roll. See for example \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/19836002\"\u003e19836002\u003c/a\u003e for an example of adding a landmine during a Blink roll. If a roll lands without a landmine (say thanks to autoroll bot), it's ok to commit a separate CL with just the landmine, ideally as close as possible after the roll, since this leaves little gap between them (you do not need to roll back and have a manual roll+landmine CL, as this is rarely necessary).\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003eQ: I have a question that's not here, whom do I bug?\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003eA: Please bug \u003ca href\u003d\"mailto:iannucci@chromium.org\"\u003eiannucci@chromium.org\u003c/a\u003e.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Details-please...\" /\u003eDetails, please...\u003c/h2\u003e\r\n\u003cdiv\u003eFor a given build:\u003c/div\u003e\r\n\u003col\u003e\u003cli\u003eCheck out some version of the code\u003c/li\u003e\r\n\u003cli\u003elandmines.py runs with the current GYP environment\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eThis calls get_landmines() for each POSSIBLE target (not just the one that's going to be built).\u003c/li\u003e\r\n\u003cli\u003eIf \u0026lt;build_dir\u0026gt;/\u0026lt;target\u0026gt;/.landmines doesn't exist, it's written with the result of get_landmines(\u0026lt;target\u0026gt;)\u003c/li\u003e\r\n\u003cli\u003eElse\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eIf the result of get_landmines(\u0026lt;target\u0026gt;) differs from the content of the .landmines file, the diff is written out to \u0026lt;build_dir\u0026gt;/\u0026lt;target\u0026gt;/.landmines_triggered .\u003c/li\u003e\r\n\u003cli\u003eElse \u0026lt;build_dir\u0026gt;/\u0026lt;target\u0026gt;/.landmines_triggered is deleted\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003ecompile.py runs with a --target passed to it\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eif \u0026lt;build_dir\u0026gt;/\u0026lt;target\u0026gt;/.landmines_triggered exists, compile.py prints the contents of the file and behaves as if --clobber was specified on the command line.\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eclobbering includes removing both .landmines and .landmines_triggered\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003c/ol\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Use-cases\" /\u003eUse cases\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Moving-generated-files\" /\u003eMoving generated files\u003c/h3\u003e\u003cdiv\u003eIf you move \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/generated-files\"\u003egenerated files\u003c/a\u003e, then you need to clobber the build, otherwise stale files may be used (if they are found earlier during header search). Subtly, this shows up only on \u003ci\u003elater\u003c/i\u003e CLs that change the generated file in the new location, but don't overwrite the stale one. See for example \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eIssue \u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d381111\" style\u003d\"font-size:10pt;background-color:transparent\"\u003e381111\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e (\u003c/span\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d381111#c4\" style\u003d\"font-size:10pt;background-color:transparent\"\u003ecomment\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003e). Further, if this change happens in a separate repository (e.g., Blink), then CLs that change the generated files don't work until the repo has rolled and a landmine has been added. I.e., the steps are:\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eSubmit Blink CL moving generated files.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eRoll Blink to Chromium, including landmine (or include in separate followup CL).\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eSubmit Blink CL changing generated files.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003col\u003e\u003col\u003e\u003col\u003e\r\n\u003c/ol\u003e\r\n\u003c/ol\u003e\r\n\u003c/ol\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4852676552341181359"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-clobber-landmines"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/298205378256273737"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4061537406890692522/4"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/298205378256273737"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/298205378256273737"}],"author":[{"name":{"$t":"Robbie Iannucci"},"email":{"$t":"iannucci@chromium.org"}}],"sites$pageName":{"$t":"chromium-clobber-landmines"},"sites$revision":{"$t":"16"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/798767683952072355"},"published":{"$t":"2011-07-12T17:01:44.913Z"},"updated":{"$t":"2014-06-06T19:14:07.998Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-15T22:11:11.751Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Acer AC700 Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Entering-Developer-Mode\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eEntering Developer Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-switch\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eDeveloper switch\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developer-mode-BIOS\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eDeveloper-mode BIOS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-going-on-here-\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eWhat's going on here?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-boot-your-own-image-from-USB\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eHow to boot your own image from USB\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-install-your-own-Chromium-OS\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHow to install your own Chromium OS image on your SSD\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Leaving-Developer-Mode\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eLeaving Developer Mode\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-One-other-thing-to-try-first\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eOne other thing to try first\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-use-the-Recovery-Mode-button\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eHow to use the Recovery Mode button\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Firmware\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eFirmware\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-s-inside-\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eWhat's inside? \u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Disassembly\"\u003e\u003cstrong\u003e8.1 \u003c/strong\u003eDisassembly\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Access-to-upgradable-cleanable-components\"\u003e\u003cstrong\u003e8.1.1 \u003c/strong\u003eAccess to upgradable/cleanable components\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Access-to-the-rest-of-the-machine\"\u003e\u003cstrong\u003e8.1.2 \u003c/strong\u003eAccess to the rest of the machine\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\nThis page contains information about the \u003ca href\u003d\"http://us.acer.com/ac/en/US/content/ac700-home\" rel\u003d\"nofollow\"\u003eAcer AC700 Chromebook\u003c/a\u003e that is interesting and/or useful to software developers.  For general \r\ninformation about getting started with developing on Chromium OS (the \r\nopen-source version of the software on Chrome OS devices), see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e.\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Entering-Developer-Mode\" /\u003eEntering Developer Mode\u003c/h2\u003e\r\nYou might want to enter developer mode if you're following the instructions in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e, or if you just want to get access to a shell on your device to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device\"\u003epoke around\u003c/a\u003e.\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eCaution: Modifications you make to the system are not supported by Google, may cause hardware\u003c/span\u003e\u003c/b\u003e\u003cb style\u003d\"font-size:10pt\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e, software or security\u003c/span\u003e\u003c/b\u003e\u003cb style\u003d\"font-size:10pt\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e issues and may void warranty.\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eDeveloper mode on the Acer AC700 has two levels of access, \r\n\"dev-switch on\" and \"dev-mode BIOS\".  With the first level you enable a \r\ncommand line shell, which lets you look around inside the GNU/Linux \r\noperating system, but does not let you run your own versions. The second\r\n level of access installs a special BIOS component that provides the \r\nability to boot your own operating systems from either removable \r\n(USB/SD) or fixed (SSD) drives. Both levels of access are completely \r\nreversible, so don't be afraid to experiment.\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-switch\" /\u003eDeveloper switch\u003c/h3\u003e\r\nThe\r\n developer switch enables the command line shell. The switch is underneath the chromebook battery. To enable the \r\ndeveloper switch you remove the battery, use something pointy to move the \r\nswitch towards the side with the red dot above it, and reboot. Note: \u003cb\u003ebe gentle\u003c/b\u003e! Some people have reported that the developer switch breaks easily.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThe first time you reboot after turning the developer switch on, your chromebook will:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eShow\r\n\r\n a scary warning that its software cannot be trusted, since a command \r\nline shell is enabled (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003eErase\r\n all personal data on the \"stateful partition\" (i.e., user accounts and \r\nsettings - no worries, though, since all data is in the cloud!).\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eMake you wait between 5 and 10 minutes while it erases the data.\u003cbr /\u003e\r\n\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\u003c/ul\u003e\r\nThe\r\n erase and wait steps only happen when you first enable the developer \r\nswitch, to help prevent someone from quickly reimaging your device while\r\n \r\nyou're away from the keyboard. Successive boots will:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eShow the same scary warning (press Ctrl-D or wait 30 seconds to dismiss).\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003e\u003cspan style\u003d\"font-style:normal;font-weight:normal\"\u003e\u003cb\u003e\u003ci\u003eContinue to boot only Google-signed images, and only from the SSD.\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003c/span\u003e\u003c/i\u003e\u003c/b\u003e\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eAt this point, verified boot is still active but because a command line shell is enabled, your system is \u003cb\u003eNOT\u003c/b\u003e secure. Refer to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device\"\u003ePoking around your Chrome OS Notebook\u003c/a\u003e\r\n to see how to access the command line shell. The message displayed at \r\nthe shell itself should tell you how to set your own password to protect\r\n shell access and make your system secure again.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nHere's a photo showing the location of the developer switch:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"display:block;margin-top:5px;margin-right:auto;margin-bottom:0pt;text-align:left\" /\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/newback.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"300\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1310490460693/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/newback.jpg?height\u003d300\u0026amp;width\u003d400\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Developer-mode-BIOS\" /\u003eDeveloper-mode BIOS\u003c/h3\u003e\r\nIf\r\n you want to make modifications to the Chrome OS filesystem or boot your\r\n own version of Chromium OS, you'll need to activate the second level of\r\n developer access. You do this by running a special command from the \r\ncommand line shell. You first log in with the username 'chronos' (if \r\nyou've set a shell password, you'll be prompted for it). Then you switch\r\n to the 'root' account, and run the command to install the \r\ndeveloper-mode BIOS. For example:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-left:40px\"\u003elocalhost login: \u003cb\u003echronos\u003c/b\u003e\u003cbr /\u003e\r\nchronos@localhost $ \u003cb\u003esudo bash\u003c/b\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"color:rgb(204,0,0)\"\u003elocalhost\u003c/span\u003e \u003cspan style\u003d\"color:rgb(0,0,255)\"\u003echronos #\u003c/span\u003e \u003cb\u003echromeos-firmwareupdate --mode\u003dtodev\u003c/b\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-What-s-going-on-here-\" /\u003eWhat's going on here?\u003c/h3\u003e\r\n\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified boot\u003c/a\u003e\r\n is the process by which Chrome OS ensures that you are running only the\r\n software that shipped with your chromebook. The process starts with the\r\n read-only BIOS, which is built into the device at the factory and can't\r\n be modified without disassembly (please don't try that; you'll void \r\nyour warranty). The read-only BIOS verifies one of two read-write BIOSes\r\n (there are two so we can provide updates if we have to with less risk \r\nof failure) and continues execution there. The read-write BIOS then \r\nverifies one of two (same reason) kernels and executes that, and the \r\nkernel verifies its root filesystem as each block is read off the SSD.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThe\r\n normal read-write BIOSes will only boot Google-signed kernels, and only\r\n from the SSD. When you run the chromeos-firmwareupdate command above, \r\nyou are replacing the primary read-write BIOS with a different one that \r\nwill allow any self-signed kernel (refer to the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e)\r\n to boot from either a removable device (by pressing Ctrl-U at the scary\r\n boot screen) or from the SSD (press Ctrl-D or wait 30 seconds).\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-boot-your-own-image-from-USB\" /\u003eHow to boot your own image from USB\u003c/h2\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eFollow the steps above to turn on the developer switch and to install the developer-mode BIOS.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eBuild a Chrome OS image using the steps in the \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\" style\u003d\"font-family:arial,sans-serif\"\u003eChromium OS Developer Guide\u003c/a\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e. It does not need to be a recovery image.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eInsert the removable drive containing your image into the left side USB slot.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eIf you use the one on the right, the USB stick's light will flash, but the screen will stay black and the machine won't boot.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eReboot, and when you see the blue scary boot screen, press Ctrl-U.\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eIt should boot your image. If for some reason it doesn't think your image is valid it will just beep once instead.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-install-your-own-Chromium-OS\" /\u003eHow to install your own Chromium OS image on your SSD\u003c/h2\u003e\r\nIf you follow the full instructions from the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide\"\u003eChromium OS Developer Guide\u003c/a\u003e,\r\n you will eventually end up with a bootable USB drive containing your \r\nimage. You can boot that image directly from the USB drive as described \r\nabove. Since it's your personal image, it should have shell access \r\nenabled. Log in as user \"chronos\" and run\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"line-height:13px\"\u003e\u003ccode\u003e/usr/sbin/chromeos-install\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nThat\r\n will wipe the SSD and install your image on it instead. When you \r\nreboot, it should attempt to boot your version. You'll still continue to\r\n see the scary boot screen at every boot, of course, as long as you are \r\nin developer mode and have the developer-mode BIOS installed, so you'll \r\nneed to press Ctrl-D or wait 30 seconds to boot.\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Leaving-Developer-Mode\" /\u003eLeaving Developer Mode\u003c/h2\u003e\r\nTo\r\n leave developer mode, simply flip the developer-mode switch back to the\r\n OFF position and reboot. One of two things will happen. If your \r\nchromebook still has a valid read-write normal-mode BIOS, Google-signed \r\nkernel, and an unmodified Chrome OS root filesystem, then that's what \r\nwill boot and you'll be back running the official Chrome OS image. Or, \r\nif you've modified any part of the verified boot chain so that a full \r\nverified boot process isn't possible, you'll be dropped into \u003ca href\u003d\"http://www.google.com/chromeos/recovery\"\u003erecovery mode\u003c/a\u003e.\r\n That will require you to create a bootable USB key to restore your \r\nchromebook to its fresh-from-the-factory state. That's annoying, but not\r\n dangerous. As long as you haven't taken the device apart, you shouldn't\r\n be able to permanently break anything.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nIn either case, all personal information will be wiped from the device during the transition.\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-One-other-thing-to-try-first\" /\u003eOne other thing to try first\u003c/h3\u003e\u003cp\u003e\r\nWhen\r\n the developer switch is on, the BIOS is not updated by any automatic \r\nChrome OS updates. If you don't think you changed anything but you still\r\n end up in recovery mode, it may be that you've haven't applied a \r\npending firmware update. Turn the developer switch back on, reboot, and \r\nfrom a root shell run\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003echromeos-firmwareupdate --mode tonormal\u003c/code\u003e\u003c/div\u003e\u003cp\u003e\r\nThat\r\n will restore the primary read-write BIOS to normal mode, which may \r\nrestore the verified boot process. Turn the developer switch off again \r\nand reboot. If you still end up in recovery mode, you'll just have to \r\nuse the recovery process to fix it.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-use-the-Recovery-Mode-button\" /\u003eHow to use the Recovery Mode button\u003c/h2\u003e\u003cp\u003e\r\nRecovery mode is a special boot operation in which the BIOS will:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eRefuse to boot from the SSD\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003ePrompt you to insert a recovery USB drive\u003c/li\u003e\r\n\u003cli\u003eOnly boot a Google-signed image from the USB drive\u003c/li\u003e\u003c/ul\u003e\u003cp\u003e\r\nYou\r\n will encounter recovery mode when the BIOS is unable to find a valid \r\nkernel to boot, either because the SSD has become corrupted or (more \r\nlikely) because you modified all the kernel partitions while in \r\ndeveloper mode and have switched back to normal mode. While in developer\r\n mode, you will be presented with the scary boot screen at every boot. \r\nPressing SPACE or RETURN will take you to recovery mode.\u003c/p\u003e\u003cp\u003e\r\nYou can \r\nalso force your chromebook into recovery mode (even in normal mode) by \r\nusing the recovery mode button. On the bottom of the Acer AC700 \r\non the side nearest the Enter key, there is a tiny pinhole:\u003c/p\u003e\r\n\u003cp style\u003d\"display:block;text-align:center;margin-right:auto;margin-left:auto\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/back.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"300\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1310490603857/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/back.jpg?height\u003d300\u0026amp;width\u003d400\" width\u003d\"400\" /\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e\r\nIf you stick a paperclip into this hole, you'll feel it press a button. \r\nTo force recovery mode, turn the device off, press this button, and while\r\n keeping it pressed, turn the device on again. This sometimes requires \r\nthree hands or a bit of contortion, but you'll know it worked when you \r\nsee the recovery screen instead of booting normally.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Firmware\" /\u003eFirmware\u003c/h2\u003e\r\n\u003cp\u003eSee the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/h2c-firmware\"\u003eH2C firmware page\u003c/a\u003e for more details.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-s-inside-\" /\u003eWhat's inside? \u003c/h2\u003e\r\n\u003cdiv\u003e\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"3\"\u003e\u003cb\u003eWARNING: Opening the case and fiddling with the stuff inside could easily brick your system and make it unrecoverable.  DO NOT ATTEMPT if you are not familiar with this process.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Disassembly\" /\u003eDisassembly\u003c/h3\u003e\r\n\u003cp\u003eTaking apart your laptop is \u003cb\u003enot\u003c/b\u003e encouraged.  If you have hardware troubles, please seek assistance first from an authorized center.  Be advised that disassembly might void warranties or other obligations, so please consult any and all paperwork your received first. \u003cspan style\u003d\"font-size:10pt\"\u003eIf you just want to see what the inside looks like, gaze upon this (click for high res versions):\u003c/span\u003e\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\r\n\u003cdiv style\u003d\"text-align:center;display:block\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/acer-zgb-bottom.jpg?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" height\u003d\"224\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1360021219268/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/acer-zgb-bottom.jpg?height\u003d224\u0026amp;width\u003d320\" width\u003d\"320\" /\u003e\u003c/a\u003e   \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/acer-zgb-bottm-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt\"\u003e\u003cimg border\u003d\"0\" height\u003d\"182\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1360021203338/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/acer-zgb-bottm-guts.jpg?height\u003d182\u0026amp;width\u003d320\" width\u003d\"320\" /\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e   \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/acer-zgb-top-guts.jpg?attredirects\u003d0\" imageanchor\u003d\"1\" style\u003d\"font-size:10pt;background-color:rgb(255,255,255)\"\u003e\u003cimg border\u003d\"0\" height\u003d\"230\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1360021225838/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook/acer-zgb-top-guts.jpg?height\u003d230\u0026amp;width\u003d320\" width\u003d\"320\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\r\n\u003cdiv style\u003d\"text-align:left;display:block\"\u003e\r\n\u003cp\u003eHowever, we acknowledge that some people like to tinker.  So here's a quick guide to taking it apart.\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Access-to-upgradable-cleanable-components\" /\u003eAccess to upgradable/cleanable components\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003eThis is very easy to do and gets you access to \u003cspan style\u003d\"font-size:10pt\"\u003eall the pieces you most likely care about:\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eThe hard drive is easy to remove \u0026amp; replace/upgrade\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIt is a standard SATA port, the form factor only allows \u003ca href\u003d\"http://www.ssd.gb.com/Products/SanDisk_Industrial_and_Enterprise/End_Of_Life/pSSD_Solid_State_Drive_(SATA)_P4Model/index.php\" rel\u003d\"nofollow\"\u003eSandisk's pSSD\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003eOnce you remove the two screws, use the black cover tab to pull down \u0026amp; remove the module\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eThe memory slots is easy to access\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThe system uses 204-Pin DDR3 SO-DIMM laptop memory\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eThe wifi module is easily removable (two screws)\u003c/li\u003e\r\n\u003cli\u003eThe RTC battery can be replaced\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eAnd here's the details:\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eGet a smallish phillips head screw driver -- all screws can be removed with just this\u003c/li\u003e\r\n\u003cli\u003eShut the system down and close the lid\u003c/li\u003e\r\n\u003cli\u003eFlip the laptop over so the bottom is facing up and the speakers are closest to you\u003c/li\u003e\r\n\u003cli\u003eRemove the three screws in the middle (on the visible plastic piece)\u003c/li\u003e\r\n\u003cli\u003eUse the tab on the right side of the plastic piece to pop it off\u003c/li\u003e\u003c/ul\u003e\r\n\u003cdiv\u003eCheck out the high res picture above for overview.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Access-to-the-rest-of-the-machine\" /\u003eAccess to the rest of the machine\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eWhile it is possible to remove the motherboard entirely, there isn't much of a point. You can see a high res image of what it looks like above if you just want that.\u003c/p\u003e\r\n\u003cp\u003eIf you really want to remove it, then here's how:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eRemove the 9 screws from the outer edges of the bottom of the case\u003c/li\u003e\r\n\u003cli\u003eFlip it over and open the display\u003c/li\u003e\r\n\u003cli\u003eThe top \u0026amp; bottom of the case should be slightly separated so you can now remove the keyboard\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThere are no screws holding it in, just tabs along the top/bottom\u003c/li\u003e\r\n\u003cli\u003eSlowly work it until you can pull it straight up through the top half of the case\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eRemove all the visible screws that were under the keyboard (there are a bunch)\u003c/li\u003e\r\n\u003cli\u003ePull the top half of the case off from the bottom\u003c/li\u003e\r\n\u003cli\u003eRemove all the visible screws from the motherboard (there are only a few)\u003c/li\u003e\r\n\u003cli\u003ePop the wires off of the wifi \u0026amp; cellular modem\u003c/li\u003e\r\n\u003cli\u003eRemove the screws from both screen hinges\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eBe careful as the LCD wire shouldn't really be removed\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eDisconnect the speakers and led module (bottom left)\u003c/li\u003e\r\n\u003cli\u003ePull the motherboard out of the case\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cul /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-ac700-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/798767683952072355"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/798767683952072355"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/798767683952072355"}],"author":[{"name":{"$t":"Bill Richardson"},"email":{"$t":"wfrichar@chromium.org"}}],"sites$pageName":{"$t":"acer-ac700-chromebook"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"XCl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1025202733608700098"},"published":{"$t":"2013-05-13T23:01:38.832Z"},"updated":{"$t":"2014-06-04T23:17:38.556Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-04T23:17:37.431Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Using requestAutocomplete()"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eThe FAQ has moved \u003ca href\u003d\"https://developer.chrome.com/multidevice/requestautocomplete-faq\"\u003ehere\u003c/a\u003e.\u003c/span\u003e\u003c/p\u003e\u003cp\u003eSee also the \u003ca href\u003d\"http://www.html5rocks.com/en/tutorials/forms/requestautocomplete/\"\u003etutorial\u003c/a\u003e and \u003ca href\u003d\"http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#dom-form-requestautocomplete\" rel\u003d\"nofollow\"\u003eHTML standard\u003c/a\u003e.\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003cp\u003e\u003cfont size\u003d\"4\"\u003eTips and tricks for developing\u003c/font\u003e\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent\"\u003eWhen testing, you should tell Chrome to use Wallet's sandbox servers so that issued card numbers will not be chargeable. Go to \u003cb\u003eabout:flags\u003c/b\u003e and enable the \"\u003cb\u003eUse Wallet Sandbox servers\u003c/b\u003e\" flag.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent\"\u003eDeveloping with Chrome's \u003cb\u003eearly release channels\u003c/b\u003e (like \u003c/span\u003e\u003ca href\u003d\"https://www.google.com/chrome/eula.html?extra\u003ddevchannel\" style\u003d\"font-size:small;background-color:transparent\" target\u003d\"_blank\"\u003edev\u003c/a\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent\"\u003e and \u003c/span\u003e\u003ca href\u003d\"https://www.google.com/chrome/eula.html?extra\u003dbetachannel\" style\u003d\"font-size:small;background-color:transparent\" target\u003d\"_blank\"\u003ebeta\u003c/a\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent\"\u003e) will give you earlier access to bug fixes and improvements such as helpful debugging messages and better i18n support. However, the majority of your site's visitors are likely to be on the stable channel.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eIf rAc is not working for you, check the \u003cb\u003edeveloper tools console \u003c/b\u003eto see if an error message was logged.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eIf you want to develop/test on an http:// site (\u003cb\u003eno SSL cert\u003c/b\u003e), you can launch Chromium with the command line flag \u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cb\u003e--reduce-security-for-testing\u003c/b\u003e\u003c/font\u003e\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003eYou can limit which address countries rAc shows by making a \u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cb\u003e\u0026lt;select\u0026gt;\u003c/b\u003e\u003c/font\u003e with one \u003cfont color\u003d\"#38761d\" face\u003d\"courier new, monospace\"\u003e\u003cb\u003e\u0026lt;option\u0026gt;\u003c/b\u003e\u003c/font\u003e per supported country.\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"2\"\u003eWhen a user chooses \u003cb\u003eWallet\u003c/b\u003e, they'll get a \u003ca href\u003d\"https://support.google.com/wallet/answer/2740044?hl\u003den\" target\u003d\"_blank\"\u003eVirtual OneTime Card\u003c/a\u003e. That's the card your site will see.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/using-requestautocomplete"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1025202733608700098"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1025202733608700098"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1025202733608700098"}],"author":[{"name":{"$t":"Paul Irish"},"email":{"$t":"paulirish@chromium.org"}}],"sites$pageName":{"$t":"using-requestautocomplete"},"sites$revision":{"$t":"25"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8017774452286975206"},"published":{"$t":"2014-06-04T04:45:49.044Z"},"updated":{"$t":"2014-06-04T04:45:49.097Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-04T04:45:49.044Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"control"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8017774452286975206"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1529733918287523195"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/server-side-test/control"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8017774452286975206"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8017774452286975206"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8017774452286975206"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8017774452286975206"}],"author":[{"name":{"$t":"Dan Shi"},"email":{"$t":"dshi@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/586209836669482826"},"published":{"$t":"2014-06-04T04:45:37.642Z"},"updated":{"$t":"2014-06-04T04:45:37.683Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-04T04:45:37.642Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"power_MyBacklightTest.py"},"summary":{},"content":{"type":"text/x-python","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/586209836669482826"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1529733918287523195"},{"rel":"alternate","type":"text/x-python","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/test-code-labs/server-side-test/power_MyBacklightTest.py"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/586209836669482826"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/586209836669482826"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/586209836669482826"},{"rel":"edit-media","type":"text/x-python","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/586209836669482826"}],"author":[{"name":{"$t":"Dan Shi"},"email":{"$t":"dshi@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDspeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2416796224212521259"},"published":{"$t":"2013-09-27T22:54:56.367Z"},"updated":{"$t":"2014-06-02T18:01:30.566Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-06-02T18:01:29.078Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"cbuildbot: Tutorial on adding data to metadata.json"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003ch3 style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Note:-Until-crbug.com-356930-is-resolved-this-applies-only-data-added-by-stages-that-run-AFTER-the-sync-stage-and-subsequent-re-execution-of-cbuildbot.\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;white-space:pre-wrap;line-height:1.15\"\u003eNote: Until \u003ca href\u003d\"http://crbug.com/356930\"\u003ecrbug.com/356930\u003c/a\u003e is resolved, this applies only data added by stages that run AFTER the sync stage and subsequent re-execution of cbuildbot.\u003c/span\u003e\u003c/h3\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;white-space:pre-wrap;line-height:1.15\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/h3\u003e\u003ch3 dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:8pt;margin-bottom:0pt\"\u003e\u003ca name\u003d\"TOC-Why-would-you-want-to-do-this-\" /\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;white-space:pre-wrap;line-height:1.15\"\u003eWhy would you want to do this?\u003c/span\u003e\u003c/h3\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:#000000;background-color:transparent;font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap\"\u003eIf you want to keep track of something that is happening on a builder and process it in a separate application, you’ll want to add it to \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003emetadata.json\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:#000000;background-color:transparent;font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap\"\u003e. This will allow you to export the necessary data in JSON format so that another program can pull it in and process it.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:#000000;background-color:#ffffff;font-weight:bold;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap\"\u003eHow to add data to metadata.json\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli style\u003d\"list-style-type:disc;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cfont face\u003d\"Arial\"\u003eDuring a run, metadata is stored in the builder run metadata object, accessible from most stages via \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eself._run.attrs.metadata\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e. Any stage which runs after the final re-execution of cbuildbot can write data to this metadata object for eventual inclusion in the uploaded metadata file. To do this, use the metadata object's \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eUpdateWithDict\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e method.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eThe final \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003emetadata.json\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e file is built and uploaded during the \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eReportStage\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e. During the run, snapshots of the metadata may be uploaded to \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003epartial-metadata.json\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e, for instance during the \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eReportBuildStartStage\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli style\u003d\"list-style-type:disc;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;background-color:transparent\"\u003e\u003cp style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003eMuch of the metadata is written by \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;color:rgb(0,0,0);font-weight:normal;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003ecbuildbot_metadata.CBuildbotMetadata.GetReportMetadataDict\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e, which is called by \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eReportStage\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e at the end of the build. However, it is generally preferrable to write metadata within the stage the first knows or produces this data, rather than waiting until the end of the build.\u003c/font\u003e\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"font-size:15.199999809265137px;line-height:13.800000190734863px;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cbr /\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8945126227284375934"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/build/cbuildbot-metadata-json-tutorial"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2416796224212521259"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2416796224212521259"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2416796224212521259"}],"author":[{"name":{"$t":"David James"},"email":{"$t":"davidjames@chromium.org"}}],"sites$pageName":{"$t":"cbuildbot-metadata-json-tutorial"},"sites$revision":{"$t":"7"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1940599759583609667"},"published":{"$t":"2011-11-11T17:53:39.705Z"},"updated":{"$t":"2014-05-28T16:42:05.052Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-15T21:10:38.015Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Aura (obsolete)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px;font-family:Verdana,Helvetica,Arial,sans-serif;text-align:left\"\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cdiv style\u003d\"display:inline;float:right;margin-top:5px;margin-right:10px;margin-bottom:5px;margin-left:10px\" /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cdiv\u003e\u003ci\u003eThis document is still good for a high level overview, with contact information, but many technical details are now obsolete; see the main \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/aura\"\u003eAura index\u003c/a\u003e for more details.\u003c/i\u003e\u003c/div\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px;font-family:Verdana,Helvetica,Arial,sans-serif;text-align:left\"\u003e\u003ca name\u003d\"TOC-Project-Goals\" /\u003eProject Goals\u003c/h3\u003e\u003cdiv style\u003d\"font-family:Verdana,Helvetica,Arial,sans-serif;line-height:16px;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana,Helvetica,Arial,sans-serif;line-height:16px;text-align:left\"\u003eThe goal is to produce a new desktop window manager and shell environment with modern capabilities. The UI must offer rich visuals, large-scale animated transitions and effects that can be produced only with the assistance of hardware acceleration.\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana,Helvetica,Arial,sans-serif;line-height:16px;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana,Helvetica,Arial,sans-serif;line-height:16px;text-align:left\"\u003eOther constraints and goals:\u003c/div\u003e\u003cdiv style\u003d\"font-family:Verdana,Helvetica,Arial,sans-serif;line-height:16px;text-align:left\"\u003e\u003cul\u003e\u003cli\u003eCross platform code, should be able to build and run on Windows (and maybe eventually other platforms), even if we don't have an initial product need for them.\u003c/li\u003e\u003cli\u003eScalable performance characteristics depending on the target hardware capability.\u003c/li\u003e\u003cli\u003eProvide the foundation of a flexible windowing system and shell for Chrome and ChromeOS on a variety of form factors.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eNotable non-goals for the initial launch of this system include:\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eMultiple monitor support. (This was added later, early 2013)\u003c/li\u003e\u003cli\u003eSoftware rendering mode or any kind of remote desktop capability to the device.\u003c/li\u003e\u003cli\u003eNPAPI plugin support. This will never be required. Pepper plugins only will be supported.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-UI-Design\" /\u003eUI Design\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003eOwner: Nicholas Jitkoff (alcor@) (UX) and Kan Liu (kanliu@) (PM)\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e\u003cbr /\u003e\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Quick-Chrome-UI-Implementation-Backgrounder\" /\u003eQuick Chrome UI Implementation Backgrounder\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eChrome UI for Chrome on Windows and Chrome OS is built using the Views UI framework that lives in src/views. The contents of a window is constructed from a hierarchy of views. View subclasses allow for implementation of various controls and components, like buttons and toolbars. Traditionally Chrome has used a mix of hand-rolled controls for aspects of its user interface where a custom look is desired, such as the browser toolbar and tabstrip, and native controls provided by the host platform where a more conventional look is desired, such as in dialog boxes and menus. When run on Windows, the Win32 API provides for native controls in the form of HWNDs, and on ChromeOS, the Gtk toolkit is used to provide native controls.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eA view hierarchy is hosted within a Widget. A Widget is a cross-platform type, and relies on a NativeWidget implementation that is specific to each host environment to perform some duties. The NativeWidget implementation is actually the connection to the host environment. For example, on Windows a NativeWidgetWin wraps a HWND (via the WindowImpl class), receives Windows messages for event handling, painting, and other tasks. In the Gtk world, a NativeWidgetGtk wraps a GtkWidget and responds to signals. The NativeWidget is responsible for translating platform-specific notifications into cross platform views::Events and other types that the rest of Views code can respond to in a platform-independent fashion.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe Chrome UI was originally written for Windows, and so despite the relatively platform-neutral nature of the View hierarchy and much of the views code, Win32-isms did creep in. The philosophy on the Chrome team has always been \"let not the perfect be the enemy of the good,\" so pathways to shorter-term success have been emphasized. The Mac and Desktop-Linux ports of Chrome pursued a different strategy for UI, more aggressively using the native toolkits offered on those platforms (Cocoa and Gtk), so at the start of the Chrome OS project there was still some considerable Win32 influence in Views code. Many of those Win32-isms have been augmented by ifdef'ed Gtkisms.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe reliance on platform widget systems has posed a problem though in that it prevents hardware acceleration of elements of the UI and arbitrary transformation of UI controls. The platform native frameworks are also peculiar in a number of ways, sharing constraints that are not relevant to desktop Chrome or Chrome OS. Before long a desire to eradicate our usage of them grew strong enough to begin work on doing so. An effort was spun up spanning several teams to start by removing Gtk usage in the Views frontend code. This has become one of the major sub-projects required for the Aura work described here.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Platform-Native-Control-aka-Gtk-HWND-Elimination\" /\u003ePlatform Native Control (aka Gtk/HWND) Elimination\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003eOwner: Emmanuel Saint-Loubert-Bié (saintlou@)\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eGtk/HWND use is pervasive. It is used everywhere from the NativeWidget implementations that host the View hierarchy down to individual dialog boxes. Here are examples of work that has been done to eliminate their use:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eConverted the Options UI to WebUI. The Options dialog boxes were massive platform-native constructs that used many Gtk widgets. Replacing the whole thing with a WebUI implementation has meant many fewer controls.\u003c/li\u003e\u003cli\u003eConverted other dialogs to WebUI. In general, if something shows in a tab or in something resembling what could be a window.open() popup (top level window), it is a candidate for conversion to WebUI. While Options was the largest conglomeration of native controls, there is a long tail of other smaller dialogs that contribute to our reliance on Gtk.\u003c/li\u003e\u003cli\u003eWritten Views-based implementations of some native controls, like Textfield. Some places do not suit conversion to WebUI - e.g. the browser frame window itself. In these cases we have to write new Views-only (often referred to as \"pure views\" in code) versions of controls like the Textfield.\u003c/li\u003e\u003cli\u003eWritten Aura-based implementations of the RenderWidgetHostView. Traditionally the RenderWidgetHostView has been a HWND or GtkWidget, and is used as a parent for windowed NPAPI plugins. Since we are only supporting Pepper plugins going forward, we did not need a native window to parent NPAPI plugins and a synthetic implementation could be done.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eWhile many of the major areas have been successfully tackled, this area remains a work in progress.\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Hardware-Accelerated-Rendering-Compositor\" /\u003eHardware Accelerated Rendering/Compositor\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003eOwner: Antoine Labour (piman@)\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAt the onset of this project Chrome was using two compositors - the compositor used by WebKit to hardware accelerate CSS transitions, and a \"Browser Compositor\" run in the UI thread of the browser process, used to implement Views transformations like whole-screen rotations.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor a number of reasons, it is desirable to unify our compositing efforts here and provide a single compositor. The primary reason is achieving acceptable performance on target hardware. It is necessary to have a single compositor and draw-pass instead of two as we have now. We would also like to unify the layer trees too at some point, although this was deemed less critical.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003eThe Browser Compositor is implemented as implementations of a ui::Compositor interface, such as a GL one and a D3D one. Antoine has been proceeding by writing a new implementation that uses the WebKit-CC compositor. This way the UI can continue to use the ui::Layer API as its render target. As mentioned, we may eventually consolidate the API between UI and WebKit.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe compositor is a distinct component in Chrome code, consuming only gfx types, WebKit (obviously) and other low level components. In the fullness of time the WebKit compositor will be extracted from WebKit further so that we do not need to drag all of WebKit into Aura and Views.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/aura-desktop-window-manager/Chrome%20Graphics%20Infrastructure.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1321035006733/developers/design-documents/aura-desktop-window-manager/Chrome%20Graphics%20Infrastructure.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Aura-WM-and-Shell\" /\u003eAura WM and Shell\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(51,51,51);font-size:15px;font-weight:bold;line-height:normal\"\u003eAura\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ci\u003eOwner: Ben Goodger (beng@) and Scott Violet (sky@)\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo allow us to perform large scale window transitions, we need to back Windows by compositor layers so that we can animate them without redrawing. This led to the development of a simple window type that supported an API compatible with (i.e. implementing the other side of the contract expected by) the Views NativeWidget type. We had initially tried to do this with a View-backed NativeWidget implementation (called NativeWidgetViews) called the views-desktop. However we still needed a platform-native widget (NativeWidgetWin/NativeWidgetGtk) to host the hierarchy. A big challenge was that pervasive in Chrome code is the concept of a gfx::NativeView/NativeWindow, which on Chrome OS and Windows was expected to resolve to a GtkWidget or an HWND. This assumption is also baked into NativeWidgetWin/NativeWidgetGtk and thus we were presented with many challenges parenting windows properly, since we could only ever offer the top level (desktop/screen-level window) as a parent to code that expected a NativeView, rather than a more localized (and probably more correct) window, because a views::View couldn't be a NativeView.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis, combined with some lingering issues with large View hierarchies led to the development of the simple aura::Window type. The aura::Window is what we consider a NativeView/NativeWindow (it typedefs thus). In the Views system, we have implemented a new NativeWidget targeting this type (NativeWidgetAura) that returns the bound aura::Window from its GetNativeView() method.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe aura::Window wraps a Compositor Layer. It also has a delegate which responds to events and paints to its layer.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eaura::Windows are similar to Views, only simpler, they are a hierarchy that live within an aura::Desktop. The aura::Desktop is bound to an aura::DesktopHost, which is where the real platform-specific code lives. There is a DesktopHost that wraps an HWND and one that wraps an X window. There is no Gtk in this world. You can think of this as us having pushed the platform specific code one layer further away from Views, out to the screen edge (as far as ChromeOS is concerned). All windows within are synthetic. The DesktopHost window receives the low level platform events, cracks them to aura::Events, targets them to aura Windows, which pass them along to their delegates. On the Views side, NativeWidgetAura is a aura::Window delegate, receives the aura::Event (which it considers a platform native event), and constructs relevant views::Event types to propagate into the embedded View hierarchy.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAura is responsible for the Window hierarchy, event cracking and propagation, and other basic window functionality (like focus, activation, etc).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eNote that despite the fact that Aura is used by Views, it does not actually use Views itself. It is at a lower level of the onion. Think of it like a raw Win32 HWND or GtkWidget.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch4 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-The-Aura-Shell-and-Chrome-Integration\" /\u003eThe Aura Shell and Chrome Integration\u003c/h4\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003eOwner: Zelidrag Hornung (zelidrag@) and David Moore (davemoore@)\u003c/i\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eA desktop environment is much more than just basic window types. We needed a playground to implement the higher level elements of the window manager, such as constraint-based moving and sizing, shell features such as the persistent launcher at the bottom of the screen, status areas, etc. Rather than build this directly into Chrome, which is huge and takes forever to link, we decided to build this as a separate component. Because it consists of UI components like the launcher and custom window frame Views, it would need to depend not just on Aura but also Views.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe product is a shell library (called aura_shell) that (eventually) we can use in Chrome when built with We also have a test runner, called aura_shell_exe. This instantiates the shell, and launches a few sample/example windows that allow us to build out and test functionality. Within the shell, models for components that would normally be populated with user data (such as apps in the launcher) come from mocked models. When instantiated in Chrome, the real data is provided.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe Chrome OS UI team has traditionally worked on many of these features and people from that team will contribute heavily to this effort.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Implementation-Strategy\" /\u003eImplementation Strategy\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSince this is a complex project, there are several sub-efforts. The breakdown above covers the main areas: Compositor, Gtk-removal, Aura and the Aura Shell/Chrome Integration.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThere is much work to be done, so we're pursuing a lot of it in parallel. While the two-compositor system in place at the start of the project isn't something we can put into production, it has let us start building out the Windowing system while the single compositor work proceeds. Likewise, getting a basic shell up and running with embedded Views widgets allows shell components like the launcher to be started while other elements of the window system are being designed and constructed. Similarly, Web-UI based components like the App List can be built in Chrome behind a flag independent of any of the rest of this work.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSince we're offering a new (native) widget system, our approach to implementing this new UI has been to consider it a new target platform for Chrome, and our work can be considered another \"port\".\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eYou can build the code by setting use_aura\u003d1 in your GYP_DEFINES. This should work from Linux or Windows. This switch should define everything else necessary to make the components above work.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3 style\u003d\"color:rgb(51,51,51);margin-top:5px;margin-right:0px;margin-bottom:5px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Major-Revision-History\" /\u003eMajor Revision History\u003c/h3\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e11/11/2011 - Ben Goodger and James Cook - revisions\u003c/i\u003e\r\n\u003c/div\u003e\u003cdiv\u003e\u003ci\u003e10/5/2011 - Ben Goodger - initial revision\u003c/i\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/aura-desktop-window-manager"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1940599759583609667"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1940599759583609667"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1940599759583609667"}],"author":[{"name":{"$t":"James Cook"},"email":{"$t":"jamescook@chromium.org"}}],"sites$pageName":{"$t":"aura-desktop-window-manager"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4561977229678884084"},"published":{"$t":"2014-05-25T13:52:28.679Z"},"updated":{"$t":"2014-05-25T13:58:02.190Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-25T13:57:58.834Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Design proposal: Verify prebuilts using content hashing"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch1 style\u003d\"text-align:center\"\u003e\u003ca name\u003d\"TOC-Verify-prebuilts-using-content-hashing\" /\u003eVerify prebuilts using content hashing\u003cbr /\u003e\u003c/h1\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eProposal status: Implemented and in production\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003eAuthor: David James \u0026lt;davidjames@\u0026gt;\u003c/div\u003e\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h2\u003e\r\n\u003cp\u003eI'd like to propose a small change to the way we verify prebuilts. This change is intended to ensure that developers do not need to build packages from source if they have not modified them locally. This should shave significant time off developer builds (e.g., up to 20 minutes, if the developer syncs at a busy time).\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-What-needs-to-be-changed-\" /\u003eWhat needs to be changed?\u003c/h2\u003e\r\n\u003cp\u003eRight now, we only use prebuilts for builds if the SHA1 of the commit that we tested exactly matches the SHA1 in the remote repository. This is needed for correctness, as explained below in the “Why is prebuilt verification needed at all?” section.\u003c/p\u003e\r\n\u003cp\u003eUnfortunately, in practice, the SHA1 of the commit we tested often differs from the SHA1 in the remote repository. This happens because when the commit queue submits a change, Gerrit adds in new metadata to the commit message, causing the prebuilts to become invalid.\u003c/p\u003e\r\n\u003cp\u003eCurrently, the commit queue accounts for this problem by just rebuilding any packages with incorrect SHA1s on the next run. This doesn’t help, though, if developers sync during the day, when many changes are being pushed by the commit queue. In that case, this problem causes developer builds to slow down significantly, as they need to rebuild many packages from source.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Proposed-solution\" /\u003eProposed solution\u003c/h2\u003e\r\n\u003cp\u003eWe should use the SHA1 of the contents of the source tree to validate the prebuilts. Unlike the commit hash, this SHA1 is unaffected by the history of the repository, or by commit messages. This ensures that users always have correct prebuilts, without causing unnecessary rebuilds.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Implementation\" /\u003eImplementation\u003c/h3\u003e\r\n\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eFirst, add the SHA1 of the contents of the source tree into the ebuild as \u003ccode\u003eCROS_WORKON_TREE\u003c/code\u003e. This can be calculated instantly using the following command:\u003cbr /\u003e\u003ccode\u003egit log -1 --format\u003d%T\u003c/code\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eNext, add \u003ccode\u003eCROS_WORKON_TREE_$CROS_WORKON_TREE\u003c/code\u003e to \u003ccode\u003eIUSE\u003c/code\u003e in \u003ccode\u003ecros-workon.eclass\u003c/code\u003e.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eFinally, remove \u003ccode\u003eCROS_WORKON_COMMIT_$CROS_WORKON_COMMIT\u003c/code\u003e from \u003ccode\u003eIUSE\u003c/code\u003e from \u003ccode\u003ecros-workon.eclass\u003c/code\u003e.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Why-is-prebuilt-verification-needed-at-all-\" /\u003eWhy is prebuilt verification needed at all?\u003c/h2\u003e\r\n\u003cp\u003eBesides the above proposal, another option for speeding up builds would be to eliminate verification of SHA1s in ebuilds entirely. This would speed up builds, but would open up developers to race conditions where they might have incorrect builds.\u003c/p\u003e\r\n\u003cp\u003eExample: If one developer sends a change through the commit queue, and another developer bypasses the commit queue at the same time, the ebuild will be marked with the latest SHA1 (including both change), but the prebuilt may only include the first change. This results in developers (and bots that use binaries) never picking up the ‘chump’ change.\u003c/p\u003e\r\n\u003cp\u003eThere are also other race conditions. Example:\u003c/p\u003e\r\n\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eA chump change is pushed to power_manager.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe incremental builder kicks off.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eAnother chump change is pushed to power_manager.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe commit queue kicks off and marks both changes as stable.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eThe incremental builder kicks off again, and doesn’t notice any changes, because its local prebuilt has the same version number as the one that was pushed by the commit queue.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\r\n\u003cp\u003eBased on the above problems, I think that we should not eliminate prebuilt verification of SHA1s, and instead use the proposed solution above.\u003c/p\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verify-prebuilts-using-content-hashing"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4561977229678884084"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4561977229678884084"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4561977229678884084"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"verify-prebuilts-using-content-hashing"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4336674595682235864"},"published":{"$t":"2014-05-23T18:39:30.183Z"},"updated":{"$t":"2014-05-23T18:39:30.219Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-23T18:39:30.183Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"npapimock.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4336674595682235864"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4927629288120429199"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/npapi-deprecation/npapimock.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4336674595682235864"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4336674595682235864"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4336674595682235864"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4336674595682235864"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"XCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6226834436523433501"},"published":{"$t":"2009-11-19T17:03:56.606Z"},"updated":{"$t":"2014-05-23T15:05:32.520Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-23T15:05:31.345Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Adding a New Package"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp\u003eHere's how you add a new package to Chromium OS:\u003c/p\u003e\r\n\u003col\u003e\r\n\u003cli\u003eCreate an ebuild file for your package \u003ccode\u003esrc/third_party/chromiumos-overlay/\u003c/code\u003e. See the ebuild(5) man page (from within your development chroot) and the other ebuilds in \u003ccode\u003esrc/third_party/portage\u003c/code\u003e and \u003ccode\u003esrc/third_party/chromiumos-overlay\u003c/code\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003efor example, the ebuild file of systemtap is placed in \u003ccode\u003esrc/third_party/chromiumos-overlay/dev-util/systemtap\u003c/code\u003e.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003eUpload the package to Localmirror of Google (require Google account).\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eCreate a \u003cb\u003eREADME.chromiumos file\u003c/b\u003e that describes the purpose of the package. If your package is a third-party package, document any custom patches that have been applied\u003c/li\u003e\r\n\u003cli\u003eAdd a dependency to your new package in one of:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003e\u003ccode\u003esrc/third_party/chromiumos-overlay/virtual/target-chromium-os\u003c/code\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIncludes the package in all images (base/release, developer, test)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ccode\u003esrc/third_party/chromiumos-overlay/virtual/target-chromium-os-dev\u003c/code\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIncludes the package in developer and test images\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ccode\u003esrc/third_party/chromiumos-overlay/virtual/target-chromium-os-test\u003c/code\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIncludes the package in test images\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003e\u003ccode\u003esrc/third_party/chromiumos-overlay/virtual/target-chromium-os-sdk\u003c/code\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eIncludes the package in the SDK itself\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/ul\u003e\r\n\u003cli\u003eIncrement the revision number of the ebuild that you modified so that incremental builds recognize the changes.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cp\u003eThe source code of the package shouldn't be placed in the \u003ccode\u003esrc/\u003c/code\u003e. emerge will download the package and store it in \u003ccode\u003e/var/lib/portage/distfiles-target/\u003c/code\u003e, and the code is compiled in \u003ccode\u003e/build/tegra2_seaboard/tmp/portage/\u003c/code\u003e. When porting a new package, we can put the package in \u003ccode\u003e/var/lib/portage/distfiles-target/\u003c/code\u003e.\u003c/p\u003e\r\n\u003cp\u003eOnce you're done, make sure your changes to do not break the build system. Then create a changelist and get it reviewed (see \u003ca href\u003d\"http://dev.chromium.org/developers/contributing-code\"\u003eContributing Code\u003c/a\u003e for details).\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Adding-a-package-to-a-running-Chromium-OS-system\" /\u003eAdding a package to a running Chromium OS system\u003c/h3\u003e\r\n\u003cp\u003eThe easiest way to add a new package, or update a package is to start \u003ccode\u003edevserver\u003c/code\u003e on the build host, and use \u003ccode\u003egmerge\u003c/code\u003e to build the package and install the results on the target device.\u003c/p\u003e\r\n\r\n\u003cp\u003eSee \u003ca href\u003d\"http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/using-the-dev-server#TOC-How-to-build-a-single-package-and-i\"\u003eUsing the dev server\u003c/a\u003e.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Adding-a-package-to-the-manifest\" /\u003eAdding a package to the manifest\u003c/h3\u003e\r\n\u003cp\u003eSee the \u003ca href\u003d\"http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/git-server-side-information#TOC-How-do-I-add-my-project-to-the-mani\"\u003eGit server-side information\u003c/a\u003e site for information about how to add your package to a manifest.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/add-a-new-package"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6226834436523433501"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6226834436523433501"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6226834436523433501"}],"author":[{}],"sites$pageName":{"$t":"add-a-new-package"},"sites$revision":{"$t":"15"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4310573542167411628"},"published":{"$t":"2014-05-23T07:35:54.494Z"},"updated":{"$t":"2014-05-23T08:57:39.110Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-23T08:57:37.755Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Exception Handling Interface"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\u003cdiv\u003eHardware exceptions (invalid memory accesses, division by zero and etc) can not be caught in the standard C/C++. Different OS provide different mechanisms to catch hardware exception. POSIX standardizes hardware exception handling via signals. Native Client doesn't support signals but it provides somewhat similar interface. The main difference is that Native Client doesn't allow to resume execution from the failed instruction. Note, that exception handling is disabled for PNaCl because exception handling interface uses platform-dependent register context.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Retrieving-Hardware-Exception-Handling-Interface\" /\u003eRetrieving Hardware Exception Handling Interface\u003c/h2\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e#include \u0026lt;irt.h\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003estruct nacl_irt_exception_handling exception_handling_interface;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003esize_t interface_size \u003d nacl_interface_query(\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e    NACL_IRT_EXCEPTION_HANDLING_v0_1,\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e    \u0026amp;exception_handling_interface,\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e    sizeof(exception_handling_interface));\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003eif (interface_size !\u003d sizeof(exception_handling_interface)) {\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e  /* error */\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e}\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Using-nacl_exception-Library\" /\u003eUsing nacl_exception Library\u003c/h2\u003e\u003cdiv\u003eAn alternative way to access hardware exception handling interface is via \u003cfont face\u003d\"courier new, monospace\"\u003enacl_exception\u003c/font\u003e library (it is part of libc). Add \u003cfont face\u003d\"courier new, monospace\"\u003e-lnacl_exception\u003c/font\u003e flag and use functions from \u003ccode\u003enacl/nacl_exception.h\u003c/code\u003e header. They have the same parameters and their names are just prefixed with \u003ccode\u003enacl_exception\u003c/code\u003e. \u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Handling-Hardware-Exceptions\" /\u003eHandling Hardware Exceptions\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eHardware exception handlers are declared as\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003etypedef void (*NaClExceptionHandler)(struct NaClExceptionContext *context);\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003ein \u003cfont face\u003d\"courier new, monospace\"\u003eirt.h\u003c/font\u003e. They receive platform-dependent hardware exception context which contains the register state. This function should not return since there is nowhere to return to. Once exception handler is called, the exception handling is disabled on this thread. You must call \u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eint exception_clear_flag(void);\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003eif you need to reenable it (you want to handle hardware exceptions inside hardware exception handler for example). This function returns 0 on success and error code on error (exception handling is disabled). If hardware exception happens on a thread where exception handling is disabled, the whole NaCl process is terminated.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe definition of \u003ccode\u003eNaClExceptionContext\u003c/code\u003e can be found in \u003ccode\u003enacl/nacl_exception.h\u003c/code\u003e header. \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eNaCl supports only one exception handler per process. The exception handler is set with\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003eint exception_handler(NaClExceptionHandler handler,\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                      NaClExceptionHandler *old_handler);\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003eThis function returns 0 on success, or error code on error (exception handling is disabled, handler is not aligned to the bundle size or outside of code region, exception handler thread is failed to start). Old exception handler is returned via old_handler parameter. In order to disable exception handling, pass \u003ccode\u003eNULL\u003c/code\u003e exception handler.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eException handler is called on current thread stack by default. If you want to set alternative stack (to handle stack overflows for example) for exception handler, use\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eint exception_stack(void *stack, size_t size);\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003eThe alternative stack is set per thread. The function returns 0 on success and error code on error (stack location is outside of NaCl address space). If you want to disable alternative stack, call this function with \u003ccode\u003eNULL\u003c/code\u003e stack pointer and zero size.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5548930097806777862"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/how-tos/exception-handling-interface"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4310573542167411628"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4310573542167411628"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4310573542167411628"}],"author":[{"email":{"$t":"halyavin@google.com"}}],"sites$pageName":{"$t":"exception-handling-interface"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"Xil7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5663733556794389665"},"published":{"$t":"2010-03-01T18:28:23.122Z"},"updated":{"$t":"2014-05-23T07:05:36.454Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-26T23:09:11.085Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Native Client"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp\u003eIf you want to write Native Client modules (because you want to put C or C++ code in your web app), get the SDK:\u003c/p\u003e\r\n\u003cblockquote\u003e\u003ca href\u003d\"http://gonacl.com\" rel\u003d\"nofollow\"\u003e\u003cb\u003eNative Client Developer Site\u003c/b\u003e\u003c/a\u003e\u003c/blockquote\u003e\r\n\u003cp\u003eIf you're interested in the implementation of Native Client, you're in the right place. We're moving our implementation information to subpages of this one, but some information exists in other websites (such as the \u003ca href\u003d\"http://code.google.com/p/nativeclient/\" style\u003d\"color:rgb(85,26,139);outline-style:none;outline-width:initial;outline-color:initial\"\u003enativeclient project\u003c/a\u003e, which has a \u003ca href\u003d\"http://code.google.com/p/nativeclient/wiki/\" target\u003d\"_blank\"\u003ewiki\u003c/a\u003e that was used for some documentation previously). The following search field covers all these websites plus groups.\u003c/p\u003e\r\n\r\n\u003cdiv\u003e\r\n\u003cimg src\u003d\"http://www.google.com/chart?chc\u003dsites\u0026amp;cht\u003dd\u0026amp;chdp\u003dsites\u0026amp;chl\u003d%5B%5BGoogle+Gadget'%3D20'f%5Cv'a%5C%3D0'10'%3D499'0'dim'%5Cbox1'b%5CF6F6F6'fC%5CF6F6F6'eC%5C0'sk'%5C%5B'%5D'a%5CV%5C%3D12'f%5C%5DV%5Cta%5C%3D10'%3D0'%3D500'%3D47'dim'%5C%3D10'%3D10'%3D500'%3D47'vdim'%5Cbox1'b%5Cva%5CF6F6F6'fC%5CC8C8C8'eC%5C'a%5C%5Do%5CLauto'f%5C\u0026amp;sig\u003deuCRKri7t9BYkRq20_OPFS3LDdo\" data-igsrc\u003d\"http://192.gmodules.com/ig/ifr?mid\u003d192\u0026amp;synd\u003dtrogedit\u0026amp;url\u003dhttp%3A%2F%2Fnativeclient.googlecode.com%2Fsvn%2Fdata%2Fsite%2Fgadget.xml\u0026amp;h\u003d50\u0026amp;w\u003d100%25\" data-type\u003d\"ggs-gadget\" data-props\u003d\"align:left;borderTitle:Native Client;height:50;igsrc:http#58//192.gmodules.com/ig/ifr?mid\u003d192\u0026amp;synd\u003dtrogedit\u0026amp;url\u003dhttp%3A%2F%2Fnativeclient.googlecode.com%2Fsvn%2Fdata%2Fsite%2Fgadget.xml\u0026amp;h\u003d50\u0026amp;w\u003d100%25;mid:192;scrolling:no;showBorder:false;showBorderTitle:null;spec:http#58//nativeclient.googlecode.com/svn/data/site/gadget.xml;width:100%;wrap:false;\" width\u003d\"500\" height\u003d\"50\" style\u003d\"display:block;text-align:left;margin-right:auto;\" class\u003d\"igm\" /\u003e\u003c/div\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cimg src\u003d\"http://www.google.com/chart?chc\u003dsites\u0026amp;cht\u003dd\u0026amp;chdp\u003dsites\u0026amp;chl\u003d%5B%5BPage+listing'%3D20'f%5Cv'a%5C%3D0'10'%3D499'0'dim'%5Cbox1'b%5CF6F6F6'fC%5CF6F6F6'eC%5C0'sk'%5C%5B%22Subpage+listing%22'%5D'a%5CV%5C%3D12'f%5C%5DV%5Cta%5C%3D10'%3D0'%3D500'%3D297'dim'%5C%3D10'%3D10'%3D500'%3D297'vdim'%5Cbox1'b%5Cva%5CF6F6F6'fC%5CC8C8C8'eC%5C'a%5C%5Do%5CLauto'f%5C\u0026amp;sig\u003dMbVUt4vxSWnPJM_hhStS4WI618E\" data-type\u003d\"subpages\" data-props\u003d\"align:left;borderTitle:Subpage listing;displayAs:gadget;maxDepth:6;rootPage:THIS_PAGE;\" width\u003d\"500\" height\u003d\"300\" style\u003d\"display:block;text-align:left;margin-right:auto;\" /\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5663733556794389665"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663733556794389665"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663733556794389665"}],"author":[{}],"sites$pageName":{"$t":"nativeclient"},"sites$revision":{"$t":"27"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/205101258490932529"},"published":{"$t":"2011-01-27T14:19:40.274Z"},"updated":{"$t":"2014-05-16T02:29:33.826Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-16T02:29:29.901Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Setting up tcpdump"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Setting-up-tcpdump\" /\u003eSetting up tcpdump\u003c/h2\u003e\u003cdiv\u003etcpdump is installed by default on test builds.  \u003cspan style\u003d\"font-family:arial;font-size:small;background-color:transparent\"\u003eYou should be able to run tcpdump to collect traces, then copy the files back to your development machine and analyze the traces with your favorite tool (tcpdump, WireShark, etc).\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1573047155342212031"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/debugging-tips/setting-up-tcpdump"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/205101258490932529"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/205101258490932529"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/205101258490932529"}],"author":[{}],"sites$pageName":{"$t":"setting-up-tcpdump"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7856162029675973689"},"published":{"$t":"2014-05-15T22:03:54.534Z"},"updated":{"$t":"2014-05-15T22:08:58.652Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-15T22:08:56.740Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Insyde H2O Firmware"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\u003cp\u003eThe first few Google Chrome OS devices used a custom firmware based on a proprietary base often referred to as \"H2C\". It's a 64 bit UEFI BIOS from \u003ca href\u003d\"http://www.insyde.com/\" rel\u003d\"nofollow\"\u003eInsyde\u003c/a\u003e named H2O (\"Hardware-2-Operating System\"), but a lot of code/features have been stripped out to significantly speed things up. Basically, everything not needed to boot Chrome OS was removed.\u003c/p\u003e\u003cp\u003eUnfortunately, this also means the firmware source cannot be released.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Version-Info\" /\u003eVersion Info\u003c/h2\u003e\r\n\u003cp\u003eThe version numbers can be broken down like so:\u003c/p\u003e\r\n\r\n\u003cul\u003e\u003cli\u003e\u0026lt;board\u0026gt;.\u0026lt;Insyde H2O core version\u0026gt;.\u0026lt;Google H2C version\u0026gt;.\u0026lt;release number\u0026gt;\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003ethe board will be Mario for the CR-48\u003c/li\u003e\r\n\u003cli\u003ethe H2O version will be three dotted values and really only have meaning to Insyde\u003c/li\u003e\r\n\u003cli\u003ethe H2C (Hardware to Chrome) version is:\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eInsyde release of 4 digits\u003c/li\u003e\r\n\u003cli\u003ethe letter 'G'\u003c/li\u003e\r\n\u003cli\u003ea number incremented by Google for each release\u003c/li\u003e\u003c/ul\u003e\u003cli\u003ethe release number for the project itself:\u003c/li\u003e\u003cul\u003e\u003cli\u003eInsyde release of 4 digits\u003c/li\u003e\u003cli\u003eletters incremented by Google for each release\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cp\u003eHere is an example from the CR-48:\u003c/p\u003e\u003cul\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eMario.03.60.1120.0038G5.0018d\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eboard: Mario\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eH2O core version: 03.60.1120\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eH2C version: 0038G5\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eInsyde release: 0038\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eGoogle release: 5\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eProject version: 0018d\u003c/li\u003e\u003cul\u003e\u003cli\u003eInsyde release: 0018\u003c/li\u003e\u003cli\u003eGoogle release: d (4th -\u0026gt; d)\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/h2c-firmware"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7856162029675973689"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7856162029675973689"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7856162029675973689"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"h2c-firmware"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1271281122993966001"},"published":{"$t":"2014-02-04T16:30:21.868Z"},"updated":{"$t":"2014-05-12T22:58:47.709Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-08T01:22:32.005Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Security Tips for Developing CRX"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003ci\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:15.600000381469727px\"\u003e(Note: Content adapted from an \u003ca href\u003d\"http://blog.chromium.org/2011/07/writing-extensions-more-securely.html\"\u003eearlier blog post on this topic\u003c/a\u003e.\u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"background-color:transparent;line-height:15.600000381469727px\"\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e)\u003c/font\u003e\u003c/span\u003e\u003c/i\u003e\u003c/div\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;line-height:15.600000381469727px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"arial, sans-serif\" size\u003d\"2\"\u003e\u003cspan style\u003d\"line-height:15.600000381469727px\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003eChrome extensions (CRX) are powerful pieces of software in modern browsers, and as such, you should help ensure that your extensions are not susceptible to security exploits. If an attacker manages to exploit a vulnerability in a CRX, they may gain access to the same privileges that the extension has. \u003c/span\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;line-height:15.600000381469727px\"\u003eThe Chrome extensions system has a number of \u003c/span\u003e\u003ca href\u003d\"http://blog.chromium.org/2009/12/security-in-depth-extension-system.html\" style\u003d\"font-family:arial,sans-serif;line-height:15.600000381469727px\"\u003ebuilt-in protections\u003c/a\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;line-height:15.600000381469727px\"\u003e to make it more difficult to introduce exploitable code, but certain coding patterns can still introduce common web vulnerabilities like cross-site scripting (XSS).\u003c/span\u003e\u003c/font\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Minimize-your-permissions\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif;line-height:15.600000381469727px\"\u003eMinimize your permissions\u003c/strong\u003e\u003c/font\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;line-height:15.600000381469727px\"\u003eThe most important thing to consider is whether you’re declaring the minimal set of permissions that you need to function. That way, if you do have a security bug in your code, the amount of permissions you’re exposing to the attacker is minimal as well. Avoid requesting \u003c/span\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e(*/*) permissions for hosts if you only need to access a couple, and don’t copy and paste your manifest from example code blindly. Review your manifest to make sure you’re only declaring what you need. This applies to permissions like tabs, history, cookies, etc. in addition to host permissions. For example, if all you’re using is \u003c/font\u003e\u003ca href\u003d\"http://code.google.com/chrome/extensions/tabs.html#method-create\" style\u003d\"font-family:arial,sans-serif\"\u003echrome.tabs.create\u003c/a\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e, you don’t actually need the tabs permission.\u003c/font\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eAnother way of minimizing install time permissions is to use \u003ca href\u003d\"https://developer.chrome.com/extensions/permissions\"\u003eoptional permissions\u003c/a\u003e. Using chrome.permissions API, you can request permissions only when you need them during runtime.\u003cbr /\u003e\u003c/font\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Use-content_security_policy-in-your-manifest\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cstrong\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eUse \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003econtent_security_policy\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e in your manifest\u003c/font\u003e\u003c/strong\u003e\u003c/font\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003ca href\u003d\"http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html\" style\u003d\"font-family:arial,sans-serif\" rel\u003d\"nofollow\"\u003eContent Security Policy\u003c/a\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e is supported in extensions via the \u003c/font\u003e\u003ca href\u003d\"http://code.google.com/chrome/extensions/trunk/manifest.html#content_security_policy\" style\u003d\"font-family:arial,sans-serif\"\u003econtent_security_policy\u003c/a\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e manifest field. This allows you to control where scripts can be executed, and it can be used to help reduce your exposure to XSS. For example, to specify that your extension loads resources only from its own package, use the following policy:\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\"content_security_policy\": \"default-src 'self'\"\u003cbr /\u003e\u003c/font\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you need to include scripts from specific hosts, you can add those hosts to this property.\u003c/font\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Don-t-use-script-src-with-an-HTTP-URL\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif\"\u003eDon’t use \u003c/strong\u003e\u003cstrong\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u0026lt;script src\u003c/font\u003e\u003c/strong\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif\"\u003e\u0026gt; with an HTTP URL\u003c/strong\u003e\u003c/font\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eWhen you include javascript into your pages using an HTTP URL, you’re opening your extension up to man-in-the-middle (MITM) attacks. When you do so in a content script, you have a similar effect on the pages you’re injected into. An attacker on the same network as one of your users could replace the contents of the script with content that they control. If that happens, they could do anything that your page can do.\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf you need to fetch a remote script, always use HTTPS from a trusted source.\u003c/font\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Don-t-use-eval-\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif\"\u003eDon’t use \u003c/strong\u003e\u003cstrong\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eeval()\u003c/font\u003e\u003c/strong\u003e\u003c/font\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThe \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eeval()\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e function is very (too!) powerful, and you should avoid using it unless absolutely necessary. Where did the code come from that you passed into \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eeval()\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e? If it came from an HTTP URL, you’re vulnerable to a MITM attack.\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e If any of the content that you passed into \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eeval()\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e is based on content from a random web page the user visits, you’re vulnerable to content escaping bugs. For example, let’s say that you have some code that looks like this:\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"courier new, monospace\"\u003efunction displayAddress(address) { // address was detected and grabbed from the current page\u003cbr /\u003e\u003cspan\u003e    \u003c/span\u003eeval(\"alert('\" + address + \"')\");\u003cbr /\u003e}\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIf it turned out that you had a bug in your parsing code, the address might wind up looking something like this:\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e'); dosomethingevil();\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThere’s almost always a better alternative to using \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eeval()\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e. For example, you can use \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003eJSON.parse\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e if you want to parse JSON (with the added benefit that it runs faster).\u003c/font\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Don-t-use-innerHTML-or-document.write-\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif\"\u003eDon’t use \u003c/strong\u003e\u003cstrong\u003e\u003cfont face\u003d\"courier new, monospace\"\u003einnerHTML\u003c/font\u003e\u003c/strong\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif\"\u003e or \u003c/strong\u003e\u003cstrong\u003e\u003cfont face\u003d\"courier new, monospace\"\u003edocument.write()\u003c/font\u003e\u003c/strong\u003e\u003c/font\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIt’s really tempting to use \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003einnerHTML\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e because it’s much simpler to generate markup dynamically than to create DOM nodes one at a time. However, this sets you up for XSS bugs. For example:\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"courier new, monospace\"\u003efunction displayAddress(address) { // address was detected and grabbed from the current page\u003cbr /\u003e\u003cspan\u003e    \u003c/span\u003emyDiv.innerHTML \u003d \"\u0026lt;b\u0026gt;\" + address + \"\u0026lt;/b\u0026gt;\");\u003cbr /\u003e}\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThis would allow an attacker to make an address like the following and once again run some script in your page:\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u0026lt;script\u0026gt;dosomethingevil();\u0026lt;/script\u0026gt;\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eInstead of \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003einnerHTML\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e, you can manually create DOM nodes and use \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003einnerText\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e to insert dynamic content.\u003c/font\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Beware-of-external-content\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cstrong style\u003d\"font-family:arial,sans-serif\"\u003eBeware of external content\u003c/strong\u003e\u003c/font\u003e\u003c/h2\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eIn general, if you’re generating dynamic content based on data from outside of your extension (such as something you fetched from the network, something you parsed from a page, or a message you received from another extension, etc.), you should be extremely careful about how you use and display it. If you use this data to generate content within your extension, you might be opening your users up to increased risk.\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Additional-Resources\" /\u003e\u003cfont size\u003d\"2\"\u003e\u003cb\u003eAdditional Resources\u003c/b\u003e\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small;background-color:transparent\"\u003eAdditional security tips and examples for Content Scripts in our \u003c/span\u003e\u003ca href\u003d\"https://developer.chrome.com/extensions/content_scripts.html#security-considerations\" style\u003d\"font-size:small;background-color:transparent\"\u003eExtension Developer Docs\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"http://kyleosborn.com/bh2012/advanced-chrome-extension-exploitation-WHITEPAPER.pdf\" style\u003d\"background-color:transparent;font-size:10pt\" rel\u003d\"nofollow\"\u003eAdvanced Chrome Extension Exploitation Leveraging API powers for Better Evil\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e (by \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ekrzysztof@kotowicz.net and \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ekos@kos.io)\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://docs.google.com/document/d/1RamP4-HJ7GAJY3yv2ju2cK50K9GhOsydJN6KIO81das/pub\"\u003eSecurity guidelines for Chrome Extension \u0026amp; App API developers\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/346879369230755664"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/education/security-tips-for-crx-and-apps"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1271281122993966001"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1271281122993966001"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1271281122993966001"}],"author":[{"name":{"$t":"Parisa Tabriz"},"email":{"$t":"parisa@chromium.org"}}],"sites$pageName":{"$t":"security-tips-for-crx-and-apps"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7045496564366115101"},"published":{"$t":"2013-10-23T01:27:03.887Z"},"updated":{"$t":"2014-05-12T18:30:26.803Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-12T18:30:25.129Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Building for Beaglebone"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eBuilding for beaglebone uses the standard build tools, with only minor \u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eadjustments to the options.\u003c/span\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cbr /\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Build-options\" /\u003eBuild options\u003c/h4\u003e\u003cdiv\u003eRun setup_board with the standard options:\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003e  ./setup_board --board\u003dbeaglebone\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eRun build_packages with these options:\u003c/span\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e  ./build_packages --board\u003dbeaglebone --nowithtest --nowithautotest --nowithfactory\u003c/code\u003e\u003c/span\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003eAssign a password to the 'chronos' account with the standard commands:\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003e  ./enable_localaccount.sh chronos\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  ./set_shared_user_password.sh\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eRun build_image with these options:\u003c/span\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e  ./build_image --board\u003dbeaglebone base\u003c/code\u003e\u003c/div\u003e\u003c/span\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003ePut the image onto a micro-SD card with a command similar to this:\u003c/span\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e  cros flash usb:// ../build/images/beaglebone/latest/chromiumos_base_image.bin\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Connecting-to-the-serial-console\" /\u003eConnecting to the serial console\u003c/h4\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003ePlug the USB cable into an Ubuntu system.\u003c/li\u003e\u003cli\u003eRun these commands on the Ubuntu system.\u003cbr /\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;line-height:1;font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003esudo modprobe ftdi_sio vendor\u003d0x0403 product\u003d0xa6d0\u003c/code\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;line-height:1;font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003esudo screen /dev/ttyUSB1 115200\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#0000ff\"\u003e\u003cb\u003eNote: \u003c/b\u003eIn some cases, the tty device may be \u003ccode\u003e/dev/ttyUSB0\u003c/code\u003e instead\u003c/font\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Booting-Chrome-OS-on-the-Beaglebone\" /\u003eBooting Chrome OS on the Beaglebone\u003c/h4\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003ePlug the micro-SD card into the beaglebone, and apply power.  With the beaglebone \u003cb\u003eblack\u003c/b\u003e, hold down \u003cb\u003eS2\u003c/b\u003e button on board before applying power.  Attach to the \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003ebeaglebone console, hit return, and type 'boot' at the U-Boot prompt.\u003c/span\u003e\u003c/div\u003e\u003cbr style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cspan style\u003d\"font-family:arial,sans-serif\"\u003e\u003cfont color\u003d\"#0000ff\"\u003e\u003cb\u003eNote:\u003c/b\u003e Power the beaglebone using the 5V barrel connector.  USB power will usually work but will fail when doing an operation with a high power draw (e.g. update_engine).\u003c/font\u003e\u003c/span\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2820759774765985493"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide/beaglebone"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7045496564366115101"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7045496564366115101"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7045496564366115101"}],"author":[{"email":{"$t":"gauravsh@chromium.org"}}],"sites$pageName":{"$t":"beaglebone"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3941764811599211136"},"published":{"$t":"2014-05-08T23:26:41.561Z"},"updated":{"$t":"2014-05-08T23:27:05.862Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-08T23:27:05.789Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"output_optimized_frame.gif"},"summary":{},"content":{"type":"image/gif","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3941764811599211136"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"image/gif","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/output_optimized_frame.gif"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3941764811599211136"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3941764811599211136"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3941764811599211136"},{"rel":"edit-media","type":"image/gif","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3941764811599211136"}],"author":[{}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5808794153464218428"},"published":{"$t":"2014-05-08T22:21:59.573Z"},"updated":{"$t":"2014-05-08T22:21:59.628Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-08T22:21:59.573Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"inbox_frameviewer_trace"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5808794153464218428"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/inbox_frameviewer_trace"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5808794153464218428"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5808794153464218428"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5808794153464218428"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5808794153464218428"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7520738834923482128"},"published":{"$t":"2014-05-08T22:21:50.300Z"},"updated":{"$t":"2014-05-08T22:21:50.334Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-08T22:21:50.300Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"nytimes_scroll_trace"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7520738834923482128"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/nytimes_scroll_trace"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7520738834923482128"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7520738834923482128"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7520738834923482128"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7520738834923482128"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2669244058932491555"},"published":{"$t":"2014-05-08T22:21:45.375Z"},"updated":{"$t":"2014-05-08T22:21:45.416Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-08T22:21:45.375Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"inbox_normal_trace"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2669244058932491555"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/inbox_normal_trace"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2669244058932491555"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2669244058932491555"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2669244058932491555"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2669244058932491555"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6034782961695489733"},"published":{"$t":"2014-05-08T22:21:38.138Z"},"updated":{"$t":"2014-05-08T22:21:38.187Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-08T22:21:38.138Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"repaint_example_trace"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6034782961695489733"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/repaint_example_trace"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6034782961695489733"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6034782961695489733"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6034782961695489733"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6034782961695489733"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7845927040787896119"},"published":{"$t":"2014-05-08T22:21:32.253Z"},"updated":{"$t":"2014-05-08T22:21:32.287Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-08T22:21:32.253Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"repaint_example_reduced_trace"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7845927040787896119"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5842750681016496414"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/using-frameviewer/repaint_example_reduced_trace"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7845927040787896119"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7845927040787896119"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7845927040787896119"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7845927040787896119"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8240479126435884388"},"published":{"$t":"2014-05-06T19:36:58.525Z"},"updated":{"$t":"2014-05-06T19:36:58.569Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-06T19:36:58.525Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stout-bare-bottom.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8240479126435884388"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-bare-bottom.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8240479126435884388"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8240479126435884388"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8240479126435884388"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8240479126435884388"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8924951843223163997"},"published":{"$t":"2014-05-06T19:36:48.864Z"},"updated":{"$t":"2014-05-06T19:36:48.897Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-06T19:36:48.864Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stout-bare-top.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8924951843223163997"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-bare-top.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8924951843223163997"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8924951843223163997"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8924951843223163997"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8924951843223163997"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1395651435218831010"},"published":{"$t":"2014-05-06T19:36:39.686Z"},"updated":{"$t":"2014-05-06T19:36:39.723Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-06T19:36:39.686Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stout-inside-bottom.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1395651435218831010"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-inside-bottom.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1395651435218831010"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1395651435218831010"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1395651435218831010"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1395651435218831010"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3783284754566977000"},"published":{"$t":"2014-05-06T19:36:27.491Z"},"updated":{"$t":"2014-05-06T19:36:27.520Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-06T19:36:27.491Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"stout-inside-top.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3783284754566977000"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7616793841804860184"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/lenovo-thinkpad-x131e-chromebook/stout-inside-top.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3783284754566977000"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3783284754566977000"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3783284754566977000"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3783284754566977000"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/149632176847739895"},"published":{"$t":"2014-04-22T21:24:51.440Z"},"updated":{"$t":"2014-05-01T17:56:37.458Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-05-01T17:56:35.412Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Controlling Enabled Consoles"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Enabling-Specific-tty-Devices\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eEnabling Specific tty Devices\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Temporary-Testing\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eTemporary Testing\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Changing-Board-Defaults\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eChanging Board Defaults\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Which-tty-are-available-\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eWhich tty are available?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eThe set of enabled consoles (serial tty or virtual terminal (VT)) used to require a combination of USE flags and custom package installs. With the new chromeos-base/tty package, all you have to do is set a single variable in your \u003ccode\u003emake.conf\u003c/code\u003e.\u003c/p\u003e\r\n\u003cp\u003eBy default, only tty2 is enabled.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Enabling-Specific-tty-Devices\" /\u003eEnabling Specific tty Devices\u003c/h2\u003e\r\n\u003cp\u003eEach tty device will have an init script in \u003ccode\u003e/etc/init\u003c/code\u003e with a name like \u003ccode\u003econsole-tty1.conf\u003c/code\u003e.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Temporary-Testing\" /\u003eTemporary Testing\u003c/h3\u003e\r\n\u003cp\u003eYou can declare which console to activate through the \u003ccode\u003eTTY_CONSOLE\u003c/code\u003e expanded flag.\u003c/p\u003e\r\n\u003cp\u003eIf you do not want to rebuild the whole system, you can just rebuild chromeos-base/tty with the right flag:\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003eUSE\u003d\"tty_console_tty1 tty_console_tty2\" emerge-${BOARD} chromeos-base/tty\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Changing-Board-Defaults\" /\u003eChanging Board Defaults\u003c/h3\u003e\r\n\u003cp\u003eIf you want your overlay to install an extra script by default, add the following line to your \u003ccode\u003emake.conf\u003c/code\u003e:\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003eTTY_CONSOLE\u003d\"${TTY_CONSOLE} tty1 ttyS0\"\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Which-tty-are-available-\" /\u003eWhich tty are available?\u003c/h2\u003e\r\n\u003cp\u003eThe tty available are listed in \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/chromeos-base/tty/tty-0.0.1.ebuild\"\u003echromeos-base/tty ebuild\u003c/a\u003e.\u003c/p\u003e\r\n\u003cp\u003eThe current list of tty's:\u003c/p\u003e\r\n\u003cdiv\u003e\r\n\u003cpre style\u003d\"margin-top:0px;margin-bottom:0px;padding-top:0.5em;font-size:medium;line-height:16.25px\"\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cspan style\u003d\"display:block\"\u003e\u003ccode\u003ettyAMA{0..5}\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"display:block\"\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:Arial,Verdana,sans-serif;background-color:transparent\"\u003e\u003ccode\u003ettyO{0..5}\u003c/code\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style\u003d\"display:block\"\u003e\u003ccode\u003ettyS{0..5}\r\n\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"display:block\"\u003e\u003ccode\u003ettySAC{0..5}\r\n\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"display:block\"\u003e\u003ccode\u003etty{0..5}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003c/pre\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2820759774765985493"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-guide/using-serial-tty"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/149632176847739895"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/149632176847739895"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/149632176847739895"}],"author":[{"name":{"$t":"Bertrand Simonnet"},"email":{"$t":"bsimonnet@chromium.org"}}],"sites$pageName":{"$t":"using-serial-tty"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7558090482949937297"},"published":{"$t":"2014-04-28T16:47:47.286Z"},"updated":{"$t":"2014-04-28T16:47:47.337Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-28T16:47:47.286Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Servo2_with_labels.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7558090482949937297"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2216022535313284907"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/for-testers/faft/Servo2_with_labels.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7558090482949937297"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7558090482949937297"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7558090482949937297"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7558090482949937297"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5919852650295317152"},"published":{"$t":"2014-04-28T16:46:29.115Z"},"updated":{"$t":"2014-04-28T16:46:29.148Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-28T16:46:29.115Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"FAFT Hardware Setup Layout.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5919852650295317152"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2216022535313284907"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/for-testers/faft/FAFT%20Hardware%20Setup%20Layout.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5919852650295317152"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5919852650295317152"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5919852650295317152"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5919852650295317152"}],"author":[{"name":{"$t":"Shawn N"},"email":{"$t":"shawnn@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7401683726684770434"},"published":{"$t":"2010-01-26T16:29:50.305Z"},"updated":{"$t":"2014-04-18T19:43:49.210Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-18T19:43:47.483Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Benchmarking Extension"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eThe Chromium Benchmarking Extension is a quick-and-dirty way to test page load time performance within Chrome.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Features\" /\u003eFeatures\u003c/h3\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eCan clear the cache between each page load\u003c/li\u003e\u003cli\u003eCan clear existing connections between each page load\u003c/li\u003e\u003cli\u003eWorks with both SPDY and HTTP \u003c/li\u003e\u003cli\u003eMeasures time-to-first-paint, overall page load time KB read/written, and several other metrics\u003c/li\u003e\u003cli\u003eCan compare performance between SPDY and HTTP\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Requirements\" /\u003eRequirements\u003c/h3\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eChrome version 7 or later\u003c/li\u003e\u003cli\u003eCommand-line flag \"--enable-benchmarking\" should be used to start chrome\u003cbr /\u003e\u003cbr /\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Screenshot\" /\u003eScreenshot\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Click-to-enlarge-\" /\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/how-the-extension-system-works/chrome-benchmarking-extension/benchmark-sm2.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1324424406858/developers/design-documents/extensions/how-the-extension-system-works/chrome-benchmarking-extension/benchmark-sm2.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/how-the-extension-system-works/chrome-benchmarking-extension/benchmark-lg.png?attredirects\u003d0\"\u003e(Click to enlarge)\u003c/a\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/h3\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Instructions\" /\u003eInstructions\u003c/h3\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cb\u003eOption 1:  Use the benchmark from the chromium source code\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003eThe benchmark is part of the chromium source code.  You'll find it here:  \u003c/div\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;border-collapse:collapse\"\u003e\u0026lt;path-to-chrome-tree\u0026gt;\\src\\chrome\\common\\extensions\\docs\\examples\\extensions\\\u003cspan style\u003d\"background-repeat:initial;background-color:rgb(255,255,204)\"\u003ebenchmark\u003c/span\u003e\u003c/span\u003e\u003cdiv\u003e\u003cspan\u003e    \u003c/span\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;border-collapse:collapse\"\u003eTo run Chrome with the benchmark, use the following command line:\u003cbr /\u003e\u003cspan\u003e    \u003c/span\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003echrome.exe --enable-benchmarking --load-extension\u003d\u0026lt;path-to-chrome-tree\u0026gt;\\src\\chrome\\common\\extensions\\docs\\examples\\extensions\\\u003c/font\u003e\u003cspan style\u003d\"background-repeat:initial;background-color:rgb(255,255,204)\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003ebenchmark\u003cbr /\u003e\u003c/font\u003e\u003c/span\u003e\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;font-size:12px;white-space:pre-wrap;background-color:transparent\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003cbr /\u003e\u003cb style\u003d\"font-family:arial,sans-serif\"\u003eOption 2: Install from Chrome Extension Gallery\u003cbr /\u003e\u003c/b\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eInstall the extension from Chrome Extension Gallery following \u003c/font\u003e\u003ca href\u003d\"https://chrome.google.com/extensions/detail/channimfdomahekjcahlbpccbgaopjll\" style\u003d\"font-family:arial,sans-serif\"\u003ethis link\u003c/a\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e. \u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eThen you'll need to restart the browser to use it.\u003c/font\u003e\u003cbr /\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003eWhen you run chrome, use:\u003c/font\u003e\u003cbr /\u003e\u003cfont face\u003d\"'courier new', monospace\" style\u003d\"font-family:arial,sans-serif\"\u003e    chrome.exe --enable-benchmarking\u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;border-collapse:collapse\"\u003eAs of M34, the method that seems to work is to load the source code as an unpacked extension after enabling developer mode and use the flag\u003c/span\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e \u003c/font\u003e\u003cspan style\u003d\"font-size:12px;white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e--enable-net-benchmarking \u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003ein addition to\u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e --enable-benchmarking\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003cfont face\u003d\"'courier new', monospace\" style\u003d\"font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003cfont face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003cspan style\u003d\"border-collapse:separate\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003cspan style\u003d\"font-size:16px;font-weight:bold\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:16px;font-weight:bold\"\u003eOptions\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:16px;font-weight:bold\"\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eIterations: How many times the test page should be loaded to collect performance date.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eClear Results: Clear result table.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eClear connectons: Reset the internal socket pool, oherwise chrome will reuse the socket connections if possible.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eClear cache: Reset the cache, otherwise chrome could load the page from cache if possible.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eEnable Spdy: Use spdy to load a page. When enabled, if the web server does not support spdy, an error is reported and test will stop.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:small\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eURL to load: A comma separated list of urls to collect performance date. Note, the urls listed here should be the final url. E.g.: if url1 will be redirect to url2, url2 should be used. Otherwise, an error will be reported and test will stop. You can use \"Load URLs From File\" to load the comma separated url list from file if your test set is large.\u003c/span\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cspan style\u003d\"font-family:arial,sans-serif;border-collapse:collapse\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cfont face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003cspan style\u003d\"border-collapse:separate\"\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cspan style\u003d\"border-collapse:separate;font-family:Arial,Verdana,sans-serif\"\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e\u003cspan style\u003d\"border-collapse:collapse\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/font\u003e\u003c/font\u003e\u003c/span\u003e\u003c/blockquote\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1413957628261797388"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/how-the-extension-system-works/chrome-benchmarking-extension"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7401683726684770434"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7401683726684770434"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7401683726684770434"}],"author":[{}],"sites$pageName":{"$t":"chrome-benchmarking-extension"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3912227166145696184"},"published":{"$t":"2013-09-10T20:11:41.986Z"},"updated":{"$t":"2014-04-17T20:11:25.609Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-09-10T21:04:27.895Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"system notifications"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h2\u003eChromeOS has several types of system status and some of them should be notified to the user. This document summarizes which types of notifications are currently used and what kind of UI flow is necessary here.\u003cdiv\u003eThe notifications are usually generated through the internal C++ API for the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/proposed-changes/apis-under-development/desktop-notification-api\"\u003edesktop notifications\u003c/a\u003e, which will appear as the \u003ca href\u003d\"http://blog.chromium.org/2013/05/rich-notifications-in-chrome.html\"\u003erich notification\u003c/a\u003e as well.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Blocking-and-system-notifications\" /\u003eBlocking and system notifications\u003c/h2\u003e\u003cdiv\u003eSometimes normal notifications should be blocked due to the current system status. For example, all notifications should be queued during the lock screen, and they should appear when unlocked. It also should be blocked when fullscreen state; notifications should be annoying when the user watches YouTube videos, or has a presentation (note: the notifications \u003cb\u003eshould\u003c/b\u003e appear in \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/immersive-fullscreen\"\u003eimmersive fullscreen\u003c/a\u003e mode instead, because the shelf / message center UI is visible in such case).\u003c/div\u003e\u003cdiv\u003eHowever, the system status could be so important that they should appear in such cases. This does not mean all system notifications should appear; some could be misleading. For example, the notification for taking screenshot would behave as same as the normal notifications, so it should not appear in the lock screen. In addition, screenshot notification has the message to 'click to view' but click should not work in lock screen. On the other hand, connecting display would be okay to be notified even in the lock screen, it just notifies the new system status.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSee also the \u003ca href\u003d\"https://docs.google.com/document/d/1Ox0Gb659lE2eusk-Gwm-a_JkARva7LydQc3hZNJvDn0/edit?usp\u003dsharing\"\u003enotification blocking code update\u003c/a\u003e design doc.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-List-of-the-system-notifications\" /\u003eList of the system notifications\u003c/h2\u003e\u003cdiv\u003e\u003ctable cellpadding\u003d\"0\" cellspacing\u003d\"0\" dir\u003d\"ltr\" style\u003d\"table-layout:fixed;font-family:arial,sans,sans-serif\"\u003e\u003ccolgroup\u003e\u003ccol width\u003d\"68\" /\u003e\u003ccol width\u003d\"92\" /\u003e\u003ccol width\u003d\"171\" /\u003e\u003ccol width\u003d\"284\" /\u003e\u003ccol width\u003d\"98\" /\u003e\u003ccol width\u003d\"70\" /\u003e\u003ccol width\u003d\"94\" /\u003e\u003ccol width\u003d\"94\" /\u003e\u003ccol width\u003d\"168\" /\u003e\u003ccol width\u003d\"102\" /\u003e\u003ccol width\u003d\"158\" /\u003e\u003c/colgroup\u003e\u003ctbody\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc;border-left:1px solid #ccc\"\u003emessage center?\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eComponent\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eSource\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204);border-top-width:1px;border-top-style:solid;border-top-color:rgb(204,204,204)\"\u003eMessage\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eShow Always? (\"System\")\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eTimeout\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eSecure? (Show on Lock Screen)\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-size:100%;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eCustomize?\u003cbr /\u003e(can be disabled)\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eClick Action\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eButton\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-top:1px solid #ccc\"\u003eTriggers\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eDisplayErrorObserver\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eCould not mirror displays...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay connection\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eDisplayErrorObserver\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eThat monitor is not supported\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay connection\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eResolutionNotificationController\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003e..resolution was changed to...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eBoth\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eAccept / Revert change\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eAccept / Revert change\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003esettings change from chrome://settings/display\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eScreenCaptureTrayItem\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003e... is sharing your screen\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eStop Capture\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eapps\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eScreenShareTrayItem\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eSharing control of your screen...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eStop Share\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eapps\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eScreenshotTaker\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eScreenshot taken\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;color:#6aa84f;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow FIles App\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003ekeyboard shortcut\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayDisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eMirroring to...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;color:#6aa84f;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow Display Settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003esettings change from chrome://settings/display, and keyboard shortcut\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayDisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eExtending screen to...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;color:#6aa84f;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow Display Settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003esettings change from chrome://settings/display, and keyboard shortcut\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003edisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayDisplay\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eDocked mode\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;color:#6aa84f;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow Display Settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eclose lid\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elanguage\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eLocaleNotificationController\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eThe language has changed from...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eAccept change\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eRevert change\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elogin\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elanguage\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayAccessability\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eSpoken feedback is enabled.\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e*\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003ekeyboard shortcut\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elanguage\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayCapsLock\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eCAPS LOCK is on\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e*\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e\u003cbr /\u003e\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003ekeyboard shortcut\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elanguage\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayIME\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eYour input method has changed...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow IME detailed view\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003ekeyboard shortcut\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eDataPromoNotification\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eGoogle Chrome will use mobile data...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e?\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003ePromo URL or settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork_connect\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eActivation of... requires a network connection\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e?\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow Settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNetworkStateNotifier\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003e...Your .. service has been activated\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e?\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow Settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNetworkStateNotifier\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eYou may have used up your mobile data...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e?\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eConfigure Network\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNetworkStateNotifier\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eFailed to connect to network...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e?\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow Settings\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003enetwork\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTraySms\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eSMS from ...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e*\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eShow SMS detailed view\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003epower\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayPower\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eBattery full OR %\u0026lt;X\u0026gt; remaining\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e*\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo / Never\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elow battery\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003epower\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayPower\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eYour Chromebook may not charge...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eusb charger connected\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003euser\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayLocallyManagedUser\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eThis user is supervised by...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003elogin\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003euser\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTraySessionLengthLimit\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;font-size:100%;vertical-align:bottom;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eThis session will end in...\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003etimeout set by policy / sync / remaining time change\u003cbr /\u003e\u003c/td\u003e\u003c/tr\u003e\u003ctr style\u003d\"height:17px\"\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;font-weight:bold;border-bottom:1px solid #ccc;border-right:1px solid #ccc;border-left:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003euser\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eTrayUser\u003c/td\u003e\u003ctd style\u003d\"padding:0px 3px;vertical-align:bottom;font-size:100%;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(204,204,204);border-right-width:1px;border-right-style:solid;border-right-color:rgb(204,204,204)\"\u003eYou can only have up to three accounts in multiple sign-in\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e*\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003e*\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eYes\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNo\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\"\u003eNone\u003c/td\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003ctd style\u003d\"padding:0 3px;vertical-align:bottom;border-bottom:1px solid #ccc;border-right:1px solid #ccc\" /\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/system-notifications"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3912227166145696184"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3912227166145696184"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3912227166145696184"}],"author":[{"name":{"$t":"Jun Mukai"},"email":{"$t":"mukai@chromium.org"}}],"sites$pageName":{"$t":"system-notifications"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2877314156099138268"},"published":{"$t":"2013-03-28T21:27:38.548Z"},"updated":{"$t":"2014-04-11T21:28:24.209Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-11T21:28:22.641Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Hacking VMX Support Into Coreboot (lumpy \u0026 stumpy)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Background\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eBackground\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Prepare-The-Device\"\u003e\u003cstrong\u003e2 \u003c/strong\u003ePrepare The Device\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Extracting-The-BIOS\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eExtracting The BIOS\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Extracting-Coreboot\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eExtracting Coreboot\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Extracting-Coreboot-RAM-Stage\"\u003e\u003cstrong\u003e3.1.1 \u003c/strong\u003eExtracting Coreboot RAM Stage\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Decompressing-Coreboot-RAM-Stage\"\u003e\u003cstrong\u003e3.1.2 \u003c/strong\u003eDecompressing Coreboot RAM Stage\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Hacking-Coreboot\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHacking Coreboot\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Locate-wrmsr\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eLocate wrmsr\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Nopping-The-wrmsr\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eNopping The wrmsr\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Repacking-The-BIOS-Image\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eRepacking The BIOS Image\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Repacking-Coreboot\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eRepacking Coreboot\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Rebuilding-Coreboot-RAM-Stage\"\u003e\u003cstrong\u003e5.1.1 \u003c/strong\u003eRebuilding Coreboot RAM Stage\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Updating-Coreboot\"\u003e\u003cstrong\u003e5.1.2 \u003c/strong\u003eUpdating Coreboot\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Updating-The-BIOS-Image\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003eUpdating The BIOS Image\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Flashing-The-New-BIOS\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eFlashing The New BIOS\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Hardware-Preparation\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003eHardware Preparation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Write-The-BIOS\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003eWrite The BIOS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Check-VMX-Support\"\u003e\u003cstrong\u003e6.3 \u003c/strong\u003eCheck VMX Support\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Enable-Write-Protect\"\u003e\u003cstrong\u003e6.4 \u003c/strong\u003eEnable Write Protect\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003e\u003cfont color\u003d\"#ff0000\" size\u003d\"4\"\u003e\u003cb\u003eIf you are not using Samsung 5 550 (lumpy) or a Samsung 3 Chromebox (stumpy), back away slowly now.  These instructions WILL NOT WORK for any other device.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nThis document is intended for people who don't mind getting their hands dirty, voiding warranties, or possibly bricking their devices.  If any of those thing scare you, just walk away.\u003c/b\u003e\u003c/font\u003e\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Background\" /\u003eBackground\u003c/h2\u003e\r\n\u003cp\u003eThe BIOS that shipped on earlier devices (such as stumpy and lumpy) had minor misfeatures in them where they would disable VMX support in the read-only firmware stage.  That means there is no way to use those virtualization extensions once you booted.  Putting into dev mode won't help, nor will installing an alternative OS.\u003c/p\u003e\r\n\u003cp\u003eThis document attempts to guide you through the process of binary patching your BIOS.  This way VMX support won't be disabled while it is loaded.  Instead, the kernel itself will take care of enabling/disabling it.  This way you can leverage that hardware functionality to use KVM or other such technologies.  The \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/running-virtual-machines-on-your-chromebook\" style\u003d\"font-size:10pt\"\u003eVirtual Machine\u003c/a\u003e explains more.\u003c/p\u003e\r\n\u003cp\u003eIf you're still here, and you have a lumpy or stumpy device, and you want to hack your BIOS (coreboot) to keep VMX (hardware virtualization insns) support from being disabled at boot, then let's get into it.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Prepare-The-Device\" /\u003ePrepare The Device\u003c/h2\u003e\r\n\u003cp\u003eMake sure your device is in dev mode already and you can get a root shell.  See the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge\"\u003eSamsung Series 5 550 Chromebook and Series 3 Chromebox\u003c/a\u003e page for details on how to do this.\u003c/p\u003e\r\n\u003cp\u003eYou should also see what version of firmware you're running.  All the example output below is taken from a Chromebox.  This will be invaluable if you ask for assistance.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ crossystem | grep fwid\r\nfwid \u003d Google_Stumpy.2.102.0 # Active firmware ID\r\nro_fwid \u003d Google_Stumpy.2.102.0 # Read-only firmware ID\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eNote that while most of these commands can be run on the device, some will require tools that are available in the Chromium OS SDK (like cbfstool and a compiler/assembler).  So you should extract the bios on the device, and then do all the other commands on your development system.  You can transfer the file via scp.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Extracting-The-BIOS\" /\u003eExtracting The BIOS\u003c/h2\u003e\r\n\u003cp\u003eNow that you're in dev mode, extract the BIOS from the read-only SPI flash using flashrom.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e# Run this on the device.\r\n$ cd /tmp\r\n$ PATH+\u003d:/sbin:/usr/sbin:/usr/local/sbin\r\n$ sudo flashrom -r bios.bin\r\n# Now scp the bios.bin off the device and do follow up commands\r\n# in your ChromiumOS sdk chroot.\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eThe BIOS can be read with fmap_decode.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ fmap_decode bios.bin\r\nfmap_signature\u003d\"0x5f5f464d41505f5f\" fmap_ver_major\u003d\"1\" fmap_ver_minor\u003d\"0\" fmap_base\u003d\"0x0000000000000000\" fmap_size\u003d\"0x800000\" fmap_name\u003d\"FMAP\" fmap_nareas\u003d\"27\"\r\narea_offset\u003d\"0x00000000\" area_size\u003d\"0x00180000\" area_name\u003d\"SI_ALL\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00000000\" area_size\u003d\"0x00001000\" area_name\u003d\"SI_DESC\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00001000\" area_size\u003d\"0x0017f000\" area_name\u003d\"SI_ME\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00180000\" area_size\u003d\"0x00680000\" area_name\u003d\"SI_BIOS\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00180000\" area_size\u003d\"0x00001000\" area_name\u003d\"RW_VPD\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00181000\" area_size\u003d\"0x00067000\" area_name\u003d\"RW_UNUSED\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x001e8000\" area_size\u003d\"0x00018000\" area_name\u003d\"RW_SHARED\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x001e8000\" area_size\u003d\"0x00004000\" area_name\u003d\"RW_ENVIRONMENT\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x001ec000\" area_size\u003d\"0x00010000\" area_name\u003d\"RW_MRC_CACHE\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x001fc000\" area_size\u003d\"0x00004000\" area_name\u003d\"DEV_CFG\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00200000\" area_size\u003d\"0x00100000\" area_name\u003d\"RW_SECTION_A\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00200000\" area_size\u003d\"0x00010000\" area_name\u003d\"VBLOCK_A\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00210000\" area_size\u003d\"0x000effc0\" area_name\u003d\"FW_MAIN_A\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x002fffc0\" area_size\u003d\"0x00000040\" area_name\u003d\"RW_FWID_A\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00300000\" area_size\u003d\"0x00100000\" area_name\u003d\"RW_SECTION_B\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00300000\" area_size\u003d\"0x00010000\" area_name\u003d\"VBLOCK_B\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00310000\" area_size\u003d\"0x000effc0\" area_name\u003d\"FW_MAIN_B\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x003fffc0\" area_size\u003d\"0x00000040\" area_name\u003d\"RW_FWID_B\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00400000\" area_size\u003d\"0x00170000\" area_name\u003d\"RO_UNUSED_1\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00570000\" area_size\u003d\"0x00020000\" area_name\u003d\"RO_VPD\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00590000\" area_size\u003d\"0x000e0000\" area_name\u003d\"RO_UNUSED_2\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00670000\" area_size\u003d\"0x00190000\" area_name\u003d\"RO_SECTION\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00670000\" area_size\u003d\"0x00000800\" area_name\u003d\"FMAP\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00670800\" area_size\u003d\"0x00000040\" area_name\u003d\"RO_FRID\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00670840\" area_size\u003d\"0x0000f7c0\" area_name\u003d\"RO_PADDING\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00680000\" area_size\u003d\"0x00080000\" area_name\u003d\"GBB\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\r\narea_offset\u003d\"0x00700000\" area_size\u003d\"0x00100000\" area_name\u003d\"BOOT_STUB\" area_flags_raw\u003d\"0x01\" area_flags\u003d\"static\"\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eHere we see all the wonderful sub-sections of the BIOS.  The one we really care about is the last part -- the BOOT_STUB.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Extracting-Coreboot\" /\u003eExtracting Coreboot\u003c/h3\u003e\r\n\u003cp\u003eUsing the details from the last line from the fmap_decode output, we can use dd to extract coreboot.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ eval `fmap_decode bios.bin | grep BOOT_STUB`\r\n$ dd if\u003dbios.bin ibs\u003d$((area_offset)) skip\u003d1 | dd bs\u003d$((area_size)) iflag\u003dfullblock of\u003dcoreboot.bin\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eYou can verify this actually worked by running the cbfstool (part of coreboot, and in the Chromium OS sdk chroot).\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ cbfstool coreboot.bin print\r\nUpdating CBFS master header to version 2\r\ncoreboot.bin: 1024 kB, bootblocksize 10498, romsize 1048576, offset 0x0\r\nAlignment: 64 bytes, architecture: x86\r\n\r\nName Offset Type Size\r\ncmos_layout.bin 0x0 cmos layout 1223\r\npci8086,0106.rom 0x500 optionrom 65536\r\nfallback/romstage 0x10540 stage 34084\r\nfallback/coreboot_ram 0x18ac0 stage 79377\r\nfallback/payload 0x2c140 payload 106157\r\nu-boot.dtb 0x46040 unknown 8144\r\n(empty) 0x48040 null 622424\r\nmrc.bin 0xdffc0 unknown 102924\r\n(empty) 0xf9240 null 17526\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Extracting-Coreboot-RAM-Stage\" /\u003eExtracting Coreboot RAM Stage\u003c/h4\u003e\r\n\u003cp\u003eWe want the coreboot_ram stage there.  Let's extract it using cbfstool.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ cbfstool coreboot.bin extract -n fallback/coreboot_ram -f coreboot_ram.lz \r\nUpdating CBFS master header to version 2\r\ncoreboot.bin: 1024 kB, bootblocksize 10498, romsize 1048576, offset 0x0\r\nAlignment: 64 bytes\r\n\r\nFound file fallback/coreboot_ram at 0x18ac0, type stage, size 79377\r\nWarning: only 'raw' files are safe to extract.\r\nSuccessfully dumped the file.\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Decompressing-Coreboot-RAM-Stage\" /\u003eDecompressing Coreboot RAM Stage\u003c/h4\u003e\r\n\u003cp\u003eYou might have noticed we called the output file here coreboot_ram.lz instead of just coreboot_ram.  That's because the stage is compressed by LZMA.  That means we need to decompress it first.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ dd if\u003dcoreboot_ram.lz ibs\u003d$((0x1c)) skip\u003d1 | lzma -dc \u0026gt; coreboot_ram.bin\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eWe skip 0x1c bytes there because that's the CBFS stage header information.  This should be constant across all images.\u003c/p\u003e\r\n\u003cp\u003eNow, finally, we have the raw x86 code that gets executed during initial boot.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Hacking-Coreboot\" /\u003eHacking Coreboot\u003c/h2\u003e\r\n\u003cp\u003eYou can do a sanity check to make sure we've got the right file by using objdump and disassembling the code.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ objdump -D -b binary -m i386 coreboot_ram.bin\r\ncoreboot_ram.bin: file format binary\r\n\r\nDisassembly of section .data:\r\n\r\n00000000 \u0026lt;.data\u0026gt;:\r\n 0: fa cli \r\n 1: 2e 0f 01 15 37 01 10 lgdtl %cs:0x100137\r\n 8: 00 \r\n 9: ea 10 00 10 00 10 00 ljmp $0x10,$0x100010\r\n 10: b8 18 00 00 00 mov $0x18,%eax\r\n 15: 8e d8 mov %eax,%ds\r\n 17: 8e c0 mov %eax,%es\r\n 19: 8e d0 mov %eax,%ss\r\n 1b: 8e e0 mov %eax,%fs\r\n 1d: 8e e8 mov %eax,%gs\r\n 1f: b0 13 mov $0x13,%al\r\n 21: e6 80 out %al,$0x80\r\n 23: fc cld \r\n...\r\n\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eYour output might not look *exactly* like that (some of the number constants might be different).  The first few instruction names should be the same though (a cli, then a lgdtl, then a ljmp, then a bunch of mov's).  If your output doesn't resemble this, then you should abort and seek help.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Locate-wrmsr\" /\u003eLocate wrmsr\u003c/h3\u003e\r\n\u003cp\u003eBuried in that output somewhere is the magic insn sequence that turns off VMX on us.  This is done by writing to the 0x3a machine specific register using the wrmsr instruction.  Let's scan the output for it.\u003c/p\u003e\r\n\u003cp\u003eThe key sequence to look for is a mov insn that stores 0x3a in the eax register, followed by a call insn to a small func that does a rdmsr+wrmsr, followed by some more movs/calls and then a cpuid insn.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ objdump -D -b binary -m i386 coreboot_ram.bin | less\r\n...\r\n 26d4d: 57 push %edi\r\n 26d4e: 31 d2 xor %edx,%edx\r\n 26d50: b8 3a 00 00 00 mov $0x3a,%eax \u0026lt;-- store of 0x3a into eax\r\n 26d55: e8 ba ff ff ff call 0x26d14 \u0026lt;-- call to local func (see below)\r\n 26d5a: ba 0f 00 00 00 mov $0xf,%edx \u0026lt;-- two move insns\r\n 26d5f: b8 e2 00 00 00 mov $0xe2,%eax\r\n 26d64: e8 ab ff ff ff call 0x26d14 \u0026lt;-- call to same local func\r\n 26d69: b8 01 00 00 00 mov $0x1,%eax\r\n 26d6e: 89 df mov %ebx,%edi\r\n 26d70: 0f a2 cpuid \u0026lt;-- cpuid call\r\n 26d72: 89 fb mov %edi,%ebx\r\n 26d74: 81 e1 00 00 00 02 and $0x2000000,%ecx\r\n 26d7a: 74 0c je 0x26d88\r\n 26d7c: 31 d2 xor %edx,%edx\r\n 26d7e: b8 3c 01 00 00 mov $0x13c,%eax\r\n 26d83: e8 8c ff ff ff call 0x26d14 \u0026lt;-- more calls to same local func\r\n 26d88: ba 1f 00 00 00 mov $0x1f,%edx\r\n 26d8d: b8 01 06 00 00 mov $0x601,%eax\r\n 26d92: e8 7d ff ff ff call 0x26d14 \u0026lt;-- more calls to same local func\r\n...\r\n\r\n# here is the func that is being called (address matches)\r\n...\r\n 26d14: 55 push %ebp \u0026lt;-- function prologue\r\n 26d15: 89 c1 mov %eax,%ecx\r\n 26d17: 89 c5 mov %eax,%ebp\r\n 26d19: 57 push %edi\r\n 26d1a: 56 push %esi\r\n 26d1b: 89 d6 mov %edx,%esi\r\n 26d1d: 0f 32 rdmsr \u0026lt;-- the rdmsr call\r\n 26d1f: 83 fe 1f cmp $0x1f,%esi\r\n 26d22: 77 11 ja 0x26d35\r\n 26d24: 89 f1 mov %esi,%ecx\r\n 26d26: bf 01 00 00 00 mov $0x1,%edi\r\n 26d2b: d3 e7 shl %cl,%edi\r\n 26d2d: 85 f8 test %edi,%eax\r\n 26d2f: 75 18 jne 0x26d49\r\n 26d31: 09 f8 or %edi,%eax\r\n 26d33: eb 10 jmp 0x26d45\r\n 26d35: 8d 4e e0 lea -0x20(%esi),%ecx\r\n 26d38: bf 01 00 00 00 mov $0x1,%edi\r\n 26d3d: d3 e7 shl %cl,%edi\r\n 26d3f: 85 fa test %edi,%edx\r\n 26d41: 75 06 jne 0x26d49\r\n 26d43: 09 fa or %edi,%edx\r\n 26d45: 89 e9 mov %ebp,%ecx\r\n 26d47: 0f 30 wrmsr \u0026lt;-- the wrmsr call\r\n 26d49: 5e pop %esi \u0026lt;-- function epilog\r\n 26d4a: 5f pop %edi\r\n 26d4b: 5d pop %ebp\r\n 26d4c: c3 ret\r\n...\r\n\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eAbove you can see the \"bad\" call to the wrmsr function happens at offset 0x26d55.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Nopping-The-wrmsr\" /\u003eNopping The wrmsr\u003c/h3\u003e\r\n\u003cp\u003eWe now have the right offset, so let's patch that particular insn to be a nop instead! :)\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ dd if\u003d/dev/zero bs\u003d5 count\u003d1 | tr '\\0' $'\\x90' | dd conv\u003dnotrunc of\u003dcoreboot_ram.bin obs\u003d$((0x26d55)) seek\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eThis will write five 0x90 bytes (the hex for the nop insn) to the offset of the call insn.  Let's see our handy work by consulting objdump.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ objdump -D -b binary -m i386 coreboot_ram.bin | less\r\n...\r\n 26d4d: 57 push %edi\r\n 26d4e: 31 d2 xor %edx,%edx\r\n 26d50: b8 3a 00 00 00 mov $0x3a,%eax \u0026lt;-- same 0x3a store into eax\r\n 26d55: 90 nop\r\n 26d56: 90 nop\r\n 26d57: 90 nop \u0026lt;-- 5 nops where there was a call\r\n 26d58: 90 nop\r\n 26d59: 90 nop\r\n 26d5a: ba 0f 00 00 00 mov $0xf,%edx \u0026lt;-- same mov insns as before\r\n 26d5f: b8 e2 00 00 00 mov $0xe2,%eax\r\n 26d64: e8 ab ff ff ff call 0x26d14\r\n...\r\n\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eYou can see that we have successfully executed our gambit!\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Repacking-The-BIOS-Image\" /\u003eRepacking The BIOS Image\u003c/h2\u003e\r\n\u003cp\u003eWe've broken everything down and made our small change.  Let's rebundle everything so we can deploy the fix on our device.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Repacking-Coreboot\" /\u003eRepacking Coreboot\u003c/h3\u003e\r\n\u003cp\u003eWe have to get creative now.  It's easier if we just let the cbfstool repack the code since it includes compressed data and checksums in the headers and other fun stuff rather than trying to do it manually using dd.\u003c/p\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Rebuilding-Coreboot-RAM-Stage\" /\u003eRebuilding Coreboot RAM Stage\u003c/h4\u003e\r\n\u003cp\u003eFirst rebuild the input ELF using the modified binary code.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ data_size\u003d`hexdump -v -e '\"%#_ax %_u\\n\"' coreboot_ram.bin | awk '$NF !\u003d \"nul\" { a \u003d $1 } END { print a }'`\r\n$ data_size\u003d$(( (data_size + 0x1000) \u0026amp; ~(0x1000 - 1) ))\r\n$ mem_size\u003d$(( `wc -c \u0026lt; coreboot_ram.bin` - data_size ))\r\n$ dd if\u003dcoreboot_ram.bin of\u003dcoreboot_ram.s.bin bs\u003d$((data_size)) count\u003d1\r\n$ printf '.incbin \"coreboot_ram.s.bin\"\\n.comm b,%s+%s,1\\n' ${mem_size} 0x44000 \u0026gt; coreboot_ram.s\r\n$ as --32 coreboot_ram.s -o coreboot_ram.o\r\n$ ld -m elf_i386 coreboot_ram.o -o coreboot_ram.elf -e 0x100000 -Ttext 0x100000\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Updating-Coreboot\" /\u003eUpdating Coreboot\u003c/h4\u003e\r\n\u003cp\u003eNow delete the existing stage from coreboot, and then add the new one.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ cp coreboot.bin coreboot.bin.new\r\n$ cbfstool coreboot.bin.new remove -n fallback/coreboot_ram\r\n$ cbfstool coreboot.bin.new add-stage -f coreboot_ram.elf -n fallback/coreboot_ram -c lzma\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eIf you look at the cbfstool print output, you might notice that the order of the components has changed (the ram stage now comes later and there is an empty hole where the ram stage used to be).  That's not a problem -- coreboot is smart enough to dynamically scan the CBFS structure for the ram stage.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Updating-The-BIOS-Image\" /\u003eUpdating The BIOS Image\u003c/h3\u003e\r\n\u003cp\u003eThis part is easiest to do with dd again.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ eval `fmap_decode bios.bin | grep BOOT_STUB`\r\n$ cp bios.bin bios.bin.new\r\n$ dd if\u003dcoreboot.bin.new of\u003dbios.bin.new obs\u003d$((area_offset)) seek\u003d1 ibs\u003d$((area_size)) count\u003d1\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Flashing-The-New-BIOS\" /\u003eFlashing The New BIOS\u003c/h2\u003e\r\n\u003cp\u003eThis is the only part where things can go wrong and possibly brick your device.  Make sure your device is fully plugged in before attempting this process (like the lumpy -- don't run it on battery).\u003c/p\u003e\r\n\u003cp\u003eThe details of each step below can be found in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge\" style\u003d\"font-size:10pt\"\u003eSamsung Series 5 550 Chromebook and Series 3 Chromebox\u003c/a\u003e page.  Consult that as you go.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Hardware-Preparation\" /\u003eHardware Preparation\u003c/h3\u003e\r\n\r\n\u003col\u003e\u003cli\u003eOpen the case\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eYou'll now have to disassemble your device (which most likely voids your warranty).  \u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003eDisable write protect\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eYou'll have to locate the Write Protect jumper and enable it.\u003c/li\u003e\r\n\u003cli\u003eThis will make the BIOS read-write so you can update it.\u003c/li\u003e\r\n\u003cli\u003eOnce things have been updated, you can undo this so your BIOS is read-only again.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003eReassemble the device\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eNow that you've done toggled the jumper, you need to reassemble the device and power it up.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003eCheck the write protect\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eRun crossystem and look at the wpsw_cur field; it should be 0.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003cli\u003ePlug your system in to be safe!\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eFor the Chromebook laptop, make sure the battery is charged, and the power supply is connected.\u003c/li\u003e\r\n\u003cli\u003eFor the Chromebox, try and plug it into a battery backup (UPS), and don't try this during a storm :).\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/ol\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Write-The-BIOS\" /\u003eWrite The BIOS\u003c/h3\u003e\r\n\u003cp\u003eWith the new bios.bin.new file in hand, let's use flashrom to update things.  Obviously you'll need to scp this file back to the device and run flashrom there.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom -w bios.bin.new\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eThen read it back out to verify things worked\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom -r bios.bin.check\r\n$ md5sum bios.bin.new bios.new.check\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eIf the md5 hashes match, then you're ready to cross your fingers and reboot!\u003c/p\u003e\r\n\u003cp\u003eIf you saw any weird errors, then do not power off the device.  Try and reprogram the original BIOS instead.\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom -w bios.bin\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Check-VMX-Support\" /\u003eCheck VMX Support\u003c/h3\u003e\r\n\u003cp\u003eNow follow the normal \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/running-virtual-machines-on-your-chromebook\"\u003eVirtual Machine\u003c/a\u003e document.  You should be able to use kvm and other fun things on your device now.\u003c/p\u003e\r\n\u003cp\u003eNote that if the initial reboot worked, you actually have to power off the device (not just reboot) in order for the relevant software registers to fully reset themselves.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Enable-Write-Protect\" /\u003eEnable Write Protect\u003c/h3\u003e\r\n\u003cp\u003eNow that you've made sure everything works, you should re-enable the write protection on your BIOS.  Follow the Hardware Preparation steps above to remove the physical jumper.\u003c/p\u003e\r\n\u003cp\u003eYou'll also have to run some software steps once you reboot.  This tells the flash to re-enable write protection on itself.  We only want to do this for the 2nd half of the flash though and not the entire thing.\u003c/p\u003e\r\n\u003cp\u003eFirst get the current status.  It should look something like:\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom --wp-status\r\nflashrom v0.9.4 : .............\r\nWP: status: 0x0000\r\nWP: status.srp0: 0\r\nWP: status.srp1: 0\r\nWP: write protect is \u003cb\u003edisabled\u003c/b\u003e.\r\nWP: write protect range: \u003cb\u003estart\u003d0x00000000, len\u003d0x00000000\u003c/b\u003e\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eNow get the flash size:\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom --get-size\r\nflashrom v0.9.4 : .............\r\n\u003cb\u003e8388608\u003c/b\u003e\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eTake that value and divide it by two and use that to re-enable write protection:\u003c/p\u003e\r\n\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom --wp-range $((8388608/2)) $((8388608/2))\r\nflashrom v0.9.4 : .............\r\n\u003cb\u003eSUCCESS\u003c/b\u003e\r\n\r\n$ sudo flashrom --wp-enable\r\nflashrom v0.9.4 : .............\r\n\u003cb\u003eSUCCESS\u003c/b\u003e\u003c/code\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003eFinally double check the result:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003ccode style\u003d\"white-space:pre\"\u003e$ sudo flashrom --wp-status\r\nflashrom v0.9.4 : .............\r\nWP: status: 0x0098\r\nWP: status.srp0: 1\r\nWP: status.srp1: 0\r\nWP: write protect is \u003cb\u003eenabled\u003c/b\u003e.\r\nWP: write protect range: \u003cb\u003estart\u003d0x00400000, len\u003d0x00400000\u003c/b\u003e\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6032530868906671964"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/samsung-sandy-bridge/coreboot-vmx-hack"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2877314156099138268"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2877314156099138268"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2877314156099138268"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"coreboot-vmx-hack"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"Xil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4780084653067904515"},"published":{"$t":"2010-12-22T22:44:06.579Z"},"updated":{"$t":"2014-04-10T20:04:11.513Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-10T20:04:10.124Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chrome Frame Troubleshooting"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Google-Chrome-Frame-is-no-longer-supported-and-retired-as-of-February-25-2014.-For-guidance-on-what-you-need-to-know-as-a-developer-or-IT-administrator-please-read-our-developer-FAQs-for-Chrome-Frame.\" /\u003e\u003cspan style\u003d\"white-space:pre-wrap;background-color:transparent\"\u003e\u003cfont color\u003d\"#ff0000\" face\u003d\"Arial\" size\u003d\"6\"\u003eGoogle Chrome Frame is no longer supported and retired as of February 25, 2014. \u003c/font\u003e\u003c/span\u003e\u003cb style\u003d\"font-size:10pt;background-color:transparent\"\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003eFor guidance on what you need to know as a developer or IT administrator, please read our \u003c/span\u003e\u003ca href\u003d\"https://developers.google.com/chrome/chrome-frame/\" style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003edeveloper FAQs\u003c/a\u003e\u003cspan style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003e for Chrome Frame.\u003c/span\u003e\u003c/font\u003e\u003c/b\u003e\u003c/h2\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003cp\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed sites-embed-full-width\" style\u003d\"width:100%;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Google-Chrome-Frame-is-no-longer-supported-and-retired-as-of-February-25-2014.-For-guidance-on-what-you-need-to-know-as-a-developer-or-IT-administrator-please-read-our-developer-FAQs-for-Chrome-Frame.\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eGoogle Chrome Frame is no longer supported and retired as of February 25, 2014. For guidance on what you need to know as a developer or IT administrator, please read our developer FAQs for Chrome Frame.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Basic-Troubleshooting-Actions-\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eBasic Troubleshooting Actions \u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Filing-a-bug\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eFiling a  bug\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Checking-if-a-Page-is-Running-in-Chrome-Frame\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003eChecking if a Page is Running in Chrome Frame\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Check-if-Chrome-Frame-is-installed\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eCheck if Chrome Frame is installed\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Common-Issues\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eCommon Issues\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-I-just-installed-Chrome-Frame-but-it-is-not-working\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eI just installed Chrome Frame but it is not working\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Is-IE-restart-required-after-installing-Chrome-Frame-for-it-to-work-\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eIs IE restart required after installing Chrome Frame for it to work? \u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-Frame-Is-Enabled-but-not-working\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003eChrome Frame Is Enabled but not working\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Can-a-server-tell-if-GCF-is-both-Installed-and-Enabled-\"\u003e\u003cstrong\u003e4.4 \u003c/strong\u003eCan a server tell if GCF is both Installed *and* Enabled?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Google-Chrome-Frame-doesn-t-work-for-site-XYZ\"\u003e\u003cstrong\u003e4.5 \u003c/strong\u003eGoogle Chrome Frame doesn't work for site XYZ\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-frame-works-but-gcf:-prefix-doesn-t-Why-\"\u003e\u003cstrong\u003e4.6 \u003c/strong\u003eChrome frame works, but gcf: prefix doesn't, Why?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-Frame-Is-Not-active-unless-I-use-the-gcf:-prefix\"\u003e\u003cstrong\u003e4.7 \u003c/strong\u003eChrome Frame Is Not active unless I use the gcf: prefix\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-CFInstall.js-s-Chrome-Frame-Detection-doesn-t-work\"\u003e\u003cstrong\u003e4.8 \u003c/strong\u003eCFInstall.js’s Chrome Frame Detection doesn't work\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Advanced-Troubleshooting\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eAdvanced Troubleshooting\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Detecting-crashes\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003eDetecting crashes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Internet-Explorer-Crash\"\u003e\u003cstrong\u003e5.1.1 \u003c/strong\u003eInternet Explorer Crash\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-Browser-Crash\"\u003e\u003cstrong\u003e5.1.2 \u003c/strong\u003eChrome Browser Crash\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-Renderer-Crash\"\u003e\u003cstrong\u003e5.1.3 \u003c/strong\u003eChrome Renderer Crash\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Reporting-crashes\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003eReporting crashes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-generate-a-crash-dump\"\u003e\u003cstrong\u003e5.2.1 \u003c/strong\u003eHow to generate a crash dump\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Detecting-stability-issues\"\u003e\u003cstrong\u003e5.3 \u003c/strong\u003eDetecting stability issues\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e \u003ca name\u003d\"h.s8mcf5tdqqh0\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\u003cp\u003e\u003ca name\u003d\"h.jb27c1-lis9f8\" /\u003e\u003c/p\u003e\u003cp\u003eThis document describes the troubleshooting flow for Google Chrome Frame users.\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Basic-Troubleshooting-Actions-\" /\u003eBasic Troubleshooting Actions\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e \u003c/span\u003e\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Filing-a-bug\" /\u003eFiling a  bug\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.xf0bgs-tnszek\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eIf the problem has serious security implications please report it using guidelines posted here: \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.chromium.org/Home/chromium-security/reporting-security-bugs\"\u003ehttp://www.chromium.org/Home/chromium-security/reporting-security-bugs\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.chromium.org/Home/chromium-security/reporting-security-bugs\" /\u003e\u003c/span\u003e\u003cspan\u003eBefore you file any bug, please search Google Chrome Frame bug tracker: \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://code.google.com/p/chromium/issues/list?q\u003dArea%3DChromeFrame\"\u003ehttp://code.google.com/p/chromium/issues/list?q\u003dArea%3DChromeFrame\u003c/a\u003e  \u003c/span\u003eIf your problem is a known issue then it’s likely that a solution is waiting for you.  If you find the bug is already there, feel free to star it so you can find it later and indicate to us another person is interested in its resolution.\u003c/p\u003e\u003cp\u003eif you can't find the bug in the database should you consider filing a new one by filling out the form here: \u003ca href\u003d\"http://code.google.com/p/chromium/issues/entry?template\u003dChromeFrame%20Issue\"\u003ehttp://code.google.com/p/chromium/issues/entry?template\u003dChromeFrame%20Issue\u003c/a\u003e If possible, provide a test page that demonstrates the problem.  Test pages help quickly fix the problem and allow us to catch regressions in future.\u003c/p\u003e\u003cp\u003e\u003cspan style\u003d\"font-size:16px;font-weight:bold\"\u003eAsking a Question on the ChromeFrame Discussion Group\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eJoin / post your question to \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame\"\u003ehttp://groups.google.com/group/google-chrome-frame\u003c/a\u003e \u003c/span\u003eThis forum is answered by Chrome Frame engineers, and is publicly-viewable, so don’t ask any sensitive/proprietary questions here.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Checking-if-a-Page-is-Running-in-Chrome-Frame\" /\u003eChecking if a Page is Running in Chrome Frame\u003c/h3\u003e\u003cp\u003e\u003cspan\u003eRight-click the page (make sure to click on the page, not on any embedded controls e.g., flash). You should see a (small-ish) context menu that shows “About Chrome Frame...” as the last option in the list.\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eIf you don’t see this, then ChromeFrame is not running this page.\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Check-if-Chrome-Frame-is-installed\" /\u003eCheck if Chrome Frame is installed\u003c/h3\u003e\u003cp\u003eWebsites are not automatically triggered to load in Chrome Frame -- the site has to explicitly trigger it.  In order for a web site to know that chrome frame is available the following should work:\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eChrome Frame is properly installed: typing “gcf:about:version” into IE address bar should display a page with version information.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eChrome Frame is enabled: you can verify that it is enabled by accessing ‘Manage Addons’ dialog via Tools menu in IE.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eTo make sure that web sites can see chrome frame, visit \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.google.com/url?q\u003dhttp%3A%2F%2Fwhatsmyuseragent.com\u0026amp;sa\u003dD\u0026amp;sntz\u003d1\u0026amp;usg\u003dAFQjCNFVJf0_Aui3AZpzlWQ1o7wZEHbkeg\"\u003ewhatsmyuseragent.com\u003c/a\u003e\u003c/span\u003e\u003cspan\u003e and see if “chromeframe/...” appears in the user-agent string.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Common-Issues\" /\u003eCommon Issues\u003c/h2\u003e\u003cp\u003e\u003ca name\u003d\"h.pxenhleaqokj\" /\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-I-just-installed-Chrome-Frame-but-it-is-not-working\" /\u003eI just installed Chrome Frame but it is not working\u003c/h3\u003e\u003cp\u003e\u003cspan\u003eMake sure that Chrome Frame is \u003c/span\u003e\u003cspan\u003einstalled and enabled\u003c/span\u003e\u003cspan\u003e. Chrome Frame plugs into Internet Explorer as a \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.google.com/url?q\u003dhttp%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fbb250436(v%3Dvs.85).aspx%23bho_whatare\u0026amp;sa\u003dD\u0026amp;sntz\u003d1\u0026amp;usg\u003dAFQjCNFTOgksXW5aAjZ0PIjbS5dDJiKVsw\"\u003eBHO\u003c/a\u003e\u003c/span\u003e\u003cspan\u003e.  When a new BHO is installed, it needs a browser restart to get loaded. However, after a fresh install,  a site can use a script on the landing page that makes sure the current browser instance gets Chrome Frame activated. \u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eIf a browser restart or reboot fixes this problem then this is very likely a BHO load after install issue.\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003cspan\u003e: \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"https://groups.google.com/group/google-chrome-frame/browse_thread/thread/517755cfbe6d31db\"\u003ehttps://groups.google.com/group/google-chrome-frame/browse_thread/thread/517755cfbe6d31db\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Is-IE-restart-required-after-installing-Chrome-Frame-for-it-to-work-\" /\u003eIs IE restart required after installing Chrome Frame for it to work?\u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003e \u003c/span\u003e\u003c/h3\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eNo, you shouldn’t need to restart after installing for it to work.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eIf it isn’t working, please file a bug.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/438390134edaf4fd#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/438390134edaf4fd#\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Chrome-Frame-Is-Enabled-but-not-working\" /\u003eChrome Frame Is Enabled but not working\u003c/h3\u003e\u003cp\u003e\u003cspan\u003eYou have installed Chrome Frame and even after the browser restart or reboot it does not work. Then you can first check if Chrome Frame is installed:\u003c/span\u003e\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eVerify that “third party browser extensions” are not disabled in IE (‘Tools’ -\u0026gt; ‘Manage Add-ons’)\u003c/span\u003e\u003c/li\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eThis can also be controlled via Group Policy, check the setting here: \u003c/span\u003e\u003cspan style\u003d\"font-family:arial;font-size:small\"\u003eComputer Configuration/Administrative Templates/Windows Components/\u003c/span\u003e\u003cspan style\u003d\"font-family:arial;font-size:small\"\u003eInternet Explorer/Internet Control Panel/Advanced Page/Alllow third-\u003c/span\u003e\u003cspan style\u003d\"font-family:arial;font-size:small\"\u003eparty browser extensions\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/6ef50d50cb09db9f/d6d0a1bc9fad0725?pli\u003d1\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/6ef50d50cb09db9f/d6d0a1bc9fad0725?pli\u003d1\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Can-a-server-tell-if-GCF-is-both-Installed-and-Enabled-\" /\u003eCan a server tell if GCF is both Installed *and* Enabled?\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.7hxz9p-2ihgzl\" /\u003e\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eCheck the user-agent string.  If the “chromeframe/...” token is present, then it is installed and enabled. \u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eIf Chrome Frame is installed but the BHO is disabled then it can be detected using script: var gcf \u003d new ActiveXObject('ChromeTab.ChromeFrame')  \u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/21cb36205d1b79a2#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/21cb36205d1b79a2#\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Google-Chrome-Frame-doesn-t-work-for-site-XYZ\" /\u003eGoogle Chrome Frame doesn't work for site XYZ\u003c/h3\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eMake sure that Chrome Frame is \u003c/span\u003e\u003cspan\u003einstalled and enabled.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eSites have to opt-in to turning on Chrome Frame, so it doesn’t automatically turn on for every site.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eMake sure that the site XYZ is sending the ChromeFrame \u0026lt;meta\u0026gt; tag, or the HTTP headers as described here: \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.chromium.org/developers/how-tos/chrome-frame-getting-started#TOC-Making-Your-Pages-Work-With-Google-\"\u003ehttp://www.chromium.org/developers/how-tos/chrome-frame-getting-started#TOC-Making-Your-Pages-Work-With-Google-\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eIf the user wants Chrome Frame on for every site, see \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.chromium.org/developers/how-tos/chrome-frame-getting-started#TOC-Testing-Your-Sites\"\u003ehttp://www.chromium.org/developers/how-tos/chrome-frame-getting-started#TOC-Testing-Your-Sites\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support threads:\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/6914c2edd167503c#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/6914c2edd167503c#\u003c/a\u003e\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/021af37c507512cd#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/021af37c507512cd#\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Chrome-frame-works-but-gcf:-prefix-doesn-t-Why-\" /\u003eChrome frame works, but gcf: prefix doesn't, Why?\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.pmls3c-yoxdep\" /\u003e\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003egcf: doesn’t work on all sites by default, for security reasons.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eTo enable this \u003c/span\u003e\u003cspan\u003etesting feature\u003c/span\u003e\u003cspan\u003e, open regedit.exe and add a DWORD value  AllowUnsafeURLs\u003d1 under HKCU\\Software\\Google\\ChromeFrame\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/38c53f04d1f6af13#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/38c53f04d1f6af13#\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Chrome-Frame-Is-Not-active-unless-I-use-the-gcf:-prefix\" /\u003eChrome Frame Is Not active unless I use the gcf: prefix\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.gc9osz-llrwhf\" /\u003e\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eMake sure the page is only sending one X-UA-Compatible \u0026lt;meta\u0026gt; tag.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eMake sure that the meta tag in in the first 1K of the page contents.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/04f133762065d471#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/04f133762065d471#\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-CFInstall.js-s-Chrome-Frame-Detection-doesn-t-work\" /\u003eCFInstall.js’s Chrome Frame Detection doesn't work\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.40yfg4-isdm4i\" /\u003e\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eMake sure the calls to CFInstall.js’s CFInstall.check() are correctly formed.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eMake sure the CFInstall.check() is performed after the \u0026lt;body\u0026gt; is loaded.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cp\u003e\u003cspan\u003eExample support thread:\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://groups.google.com/group/google-chrome-frame/browse_thread/thread/a49b91141fc84a10#\"\u003ehttp://groups.google.com/group/google-chrome-frame/browse_thread/thread/a49b91141fc84a10#\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Advanced-Troubleshooting\" /\u003eAdvanced Troubleshooting\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Detecting-crashes\" /\u003eDetecting crashes\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.ou0c72fqc21f\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eGoogle Chrome Frame plugin is loaded as npchrome_frame.dll in Internet Explorer processes.  It uses Chrome’s multi process architecture so when a web page is loaded using this plugin, it will launch a Chrome Browser process, which in turn launches a Chrome Renderer process.\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eThe following sections describe how to identify crashes in these processes.\u003c/span\u003e\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Internet-Explorer-Crash\" /\u003eInternet Explorer Crash\u003c/h4\u003e\u003cp\u003e\u003ca name\u003d\"h.rhn4wo4elzig\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eIn this case Internet Explorer will detect a crashing plugin and put up a dialog like this:\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/diagnostics/gcf_troubleshooting/image2.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1293058981006/developers/diagnostics/gcf_troubleshooting/image2.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp\u003e\u003cspan\u003eMore detailed information about the crash can be added by clicking on the ‘Advanced...’ button to bring up the crash details dialog and inserting the details in the bug report . \u003c/span\u003e\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Chrome-Browser-Crash\" /\u003eChrome Browser Crash\u003c/h4\u003e\u003cp\u003e\u003ca name\u003d\"h.8opizdph7mia\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eIf for some reason the Chrome Browser process crashed or lost connection with the plugin running in Internet Explorer, then it looks like this:\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/diagnostics/gcf_troubleshooting/image1.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1293058981006/developers/diagnostics/gcf_troubleshooting/image1.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003cp\u003e\u003cspan\u003eTo figure out if this is a crash use the following steps:\u003c/span\u003e\u003c/p\u003e\u003col\u003e\u003cli value\u003d\"1\"\u003e\u003cspan\u003eMake sure that there are no stand alone Chrome browser windows open.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eMake sure that this is the only tab or window loaded with Chrome Frame.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eOpen up task manager and look for chrome.exe processes.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eIf there are one or more chrome.exe processes in the task manager then this is a sign of a connection loss between Chrome Frame plugin and Chrome Browser process. \u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan\u003eIf there are no chrome.exe processes then it’s most likely a crash.  If this is happening at launch time then it could be a failure to launch Chrome.exe.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-Chrome-Renderer-Crash\" /\u003eChrome Renderer Crash\u003c/h4\u003e\u003cp\u003e\u003ca name\u003d\"h.z72fd3603e7s\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eIf a Chrome Renderer process crashed with Chrome Frame then it will look like this:\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/diagnostics/gcf_troubleshooting/image4.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1293058981006/developers/diagnostics/gcf_troubleshooting/image4.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cp\u003e\u003cspan\u003eIt’s very rare to have Chrome Frame specific renderer crashes. So the first thing to verify is see if the same steps lead to a crash in stand alone Chrome browser. \u003c/span\u003eIn either case, a test page that demonstrates the crash will be really helpful in the report.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Reporting-crashes\" /\u003eReporting crashes\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.crfrbrdrwlnd\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eWhile reporting a crash, having a reproducible test case is very important. If the crash is happening at random then having a crash dump is quite useful. \u003c/span\u003e\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-How-to-generate-a-crash-dump\" /\u003eHow to generate a crash dump\u003c/h4\u003e\u003cp\u003e\u003ca name\u003d\"h.1ndvaanuu5mf\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eA freely available tool called ‘Debugging Tools For Windows’ (\u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.google.com/url?q\u003dhttp%3A%2F%2Fwww.microsoft.com%2Fwhdc%2Fdevtools%2Fdebugging%2Finstallx86.mspx\u0026amp;sa\u003dD\u0026amp;sntz\u003d1\u0026amp;usg\u003dAFQjCNFhPKf3h5kZ1oBJmIEdrRMkPigeZA\"\u003e32 bit download\u003c/a\u003e\u003c/span\u003e\u003cspan\u003e \u003c/span\u003e\u003cspan\u003e\u003ca href\u003d\"http://www.google.com/url?q\u003dhttp%3A%2F%2Fwww.microsoft.com%2Fwhdc%2Fdevtools%2Fdebugging%2Finstall64bit.mspx%2520\u0026amp;sa\u003dD\u0026amp;sntz\u003d1\u0026amp;usg\u003dAFQjCNEZnFyqlcxNJW3A16kQXP4ZSSj_1w\"\u003e64 bit download\u003c/a\u003e\u003c/span\u003e\u003cspan\u003e) or ‘WinDbg’ in short, can be used to collect crash dumps.  Once you have downloaded and installed the correct flavor of WinDbg then run Internet Explorer under the debugger using the command line: \u003c/span\u003e\u003c/p\u003e\u003ccode\u003e\"c:\\Program Files\\Debugging Tools For Windows (x86)\\windbg.exe\" -g -G -o \"c:\\program files\\Internet Explorer\\iexplore.exe\"\u003c/code\u003e\u003cbr /\u003e\u003cp\u003e\u003cspan\u003eor for 64 bit OS use:\u003c/span\u003e\u003c/p\u003e\u003ccode\u003e\"c:\\Program Files\\Debugging Tools For Windows (x64)\\windbg.exe\" -g -G -o \"c:\\program files (x86)\\Internet Explorer\\iexplore.exe\"\u003c/code\u003e\u003cbr /\u003e\u003cp\u003e\u003ca name\u003d\"h.tkyhngwp1l7c\" /\u003e\u003cspan\u003eOnce Internet Explorer is launched, WinDbg should look like this:\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/diagnostics/gcf_troubleshooting/image3.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1293058981006/developers/diagnostics/gcf_troubleshooting/image3.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cp\u003e\u003cspan\u003eNow switch to Internet Explorer and follow steps to reproduce the crash.  \u003c/span\u003e\u003cspan\u003e\u003cb\u003eNote that once the crash happens, you will not see usual dialog or ‘sad tab’ bitmap. Instead, Internet Explorer will appear unresponsive\u003c/b\u003e.  \u003c/span\u003e\u003cspan\u003eWhen that happens, come back to WinDbg and it should look like this:\u003c/span\u003e\u003c/p\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/diagnostics/gcf_troubleshooting/image0.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1293058981006/developers/diagnostics/gcf_troubleshooting/image0.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cp\u003e\u003cspan\u003eType the following command into the debugger prompt as shown in the picture above and press Enter:\u003c/span\u003e\u003c/p\u003e\u003ccode\u003e.dump c:\\temp\\crash.dmp\u003c/code\u003e\u003cbr /\u003e\u003cp\u003e\u003cspan\u003eAfter the crash dump is successfully written to the disk please attach it to the bug.\u003c/span\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Detecting-stability-issues\" /\u003eDetecting stability issues\u003c/h3\u003e\u003cp\u003e\u003ca name\u003d\"h.q3rvnx-76z3cr\" /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003eSometimes Chrome Frame may not work as expected due to spyware or other buggy Internet Explorer Add-ons.  To make sure that is not the case, it’s best to test on a clean Windows image.  Also, for the purpose of testing, any other installed Add-ons can be disabled by going into ‘Tools’ -\u0026gt; ‘Manage Add-ons’ dialog in Internet Explorer.\u003c/span\u003e\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003cp\u003e\u003cspan\u003e \u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8148472531619614157"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/diagnostics/gcf_troubleshooting"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4780084653067904515"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4780084653067904515"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4780084653067904515"}],"author":[{}],"sites$pageName":{"$t":"gcf_troubleshooting"},"sites$revision":{"$t":"17"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3321550612614805569"},"published":{"$t":"2011-11-04T16:07:17.339Z"},"updated":{"$t":"2014-04-10T19:55:26.908Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-10T19:55:05.802Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chrome Frame CFInstall script"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Google-Chrome-Frame-is-no-longer-supported-and-retired-as-of-February-25-2014.-For-guidance-on-what-you-need-to-know-as-a-developer-or-IT-administrator-please-read-our-developer-FAQs-for-Chrome-Frame.\" /\u003e\u003cspan style\u003d\"background-color:transparent;white-space:pre-wrap\"\u003e\u003cfont color\u003d\"#ff0000\" face\u003d\"Arial\" size\u003d\"6\"\u003eGoogle Chrome Frame is no longer supported and retired as of February 25, 2014.\u003c/font\u003e\u003c/span\u003e\u003cfont color\u003d\"#ff0000\"\u003e\u003cspan style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003eFor guidance on what you need to know as a developer or IT administrator, please read our \u003c/span\u003e\u003ca href\u003d\"https://developers.google.com/chrome/chrome-frame/\" style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003edeveloper FAQs\u003c/a\u003e\u003cspan style\u003d\"font-family:Arial;font-size:xx-large;white-space:pre-wrap\"\u003e for Chrome Frame.\u003c/span\u003e\u003c/font\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003eThis page describes the latest version of the Chrome Frame CFInstall script that allows easy prompting for Chrome Frame installation within your own site.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis version supports a new streamlined and improved API, though it is expected to be backwards compatible with previous versions of the API as well.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-User-Experience\" /\u003eUser Experience\u003c/h2\u003e\u003cdiv\u003eThis version of the CFInstall script is designed to optimize the user's installation experience and get them onto your site, with Chrome Frame installed, as fast as possible.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTo use this install flow, simply:\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eProvide the user with a prompt to install Chrome Frame, whether it is optional or required for your site to function.\u003c/li\u003e\u003cli\u003eIf the user chooses to install Chrome Frame, invoke CFInstall.require(). You may pass optional success and failure callbacks, in that order.\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003eCFInstall.require will check the user's browser for compatibility and, if Chrome Frame is supported, launch a modal dialog with the Chrome Frame EULA and installation flow. The appropriate callback will be invoked upon installation success, failure, or cancellation.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eBy default, the current page will be reloaded after installation completes, with the Chrome Frame plugin active. Naturally, your site must be sending the Chrome Frame header or meta tag in order to be activated in Chrome Frame.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSee \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/chrome_frame/cfinstall/examples/simple.html\"\u003ehttp://src.chromium.org/viewvc/chrome/trunk/src/chrome_frame/cfinstall/examples/simple.html\u003c/a\u003e for an example of this integration.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Custom-Look-Feel\" /\u003eCustom Look \u0026amp; Feel\u003c/h2\u003e\u003cdiv\u003eThe default look \u0026amp; feel of the installation flow dialog can be replaced quite easily to match the look of your site. See \u003ca href\u003d\"http://src.chromium.org/viewvc/chrome/trunk/src/chrome_frame/cfinstall/examples/jquery.html\"\u003ehttp://src.chromium.org/viewvc/chrome/trunk/src/chrome_frame/cfinstall/examples/jquery.html\u003c/a\u003e for an example using the JQuery library.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Hosting-the-Scripts\" /\u003e\u003cb\u003eHosting the Scripts\u003c/b\u003e\u003c/h2\u003e\u003cdiv\u003eYou can access the CFInstall script directly off of Google's servers or host it yourself. If you choose to host it yourself, please note that the script consists of both the small initial script (the \"stub\") and a second, larger script (the \"implementation\") that is only downloaded if the install flow is launched. If you move the script elsewhere, you must either specify the implementation location or recompile the stub with your intended hosting path (see below).\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Specifying-a-Custom-Implementation-URL\" /\u003eSpecifying a Custom Implementation URL\u003c/h3\u003e\u003cdiv\u003eThe implementation is located at \u003ca href\u003d\"http://google.com/tools/dlpage/res/chromeframe/script/cf-xd-install-impl.js\"\u003ehttp://google.com/tools/dlpage/res/chromeframe/script/cf-xd-install-impl.js\u003c/a\u003e . If you wish to access it from elsewhere, you must make the following call before CFInstall.require:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eCFInstall.setImplementationUrl('/path/to/cf-xd-install-impl.js');\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cp\u003eNote that the path supplied may be absolute or scheme, host, or path relative (i.e. 'http://host/path/to/...', '//host/path/to/...', '/path/to', '../../path/to'). It will be resolved relative to the HTML document in which the script is executed.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Compiling-CFInstall-from-Source\" /\u003eCompiling CFInstall from Source\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eCFInstall uses the \u003ca href\u003d\"http://code.google.com/closure/library/\"\u003eClosure Library\u003c/a\u003e and is optimized using the \u003ca href\u003d\"http://code.google.com/closure/compiler/\"\u003eClosure Compiler\u003c/a\u003e. The source code for CFInstall is included in the Chromium source repository and may be checked out using the following command:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esvn co http://src.chromium.org/chrome/trunk/src/chrome_frame/cfinstall/\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eOnce you have checked out the code, you may simply run build.sh to download the required dependencies and build the optimized scripts (see the 'out' directory). The Closure Compiler requires Python and Java in order to run. If you are unable to execute build.sh (due to a lack of a shell interpreter, for example), you should find it pretty straightforward to manually invoke the compiler using the script as an example.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe build.sh script accepts two options for customizing the optimized output:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003eUsage: ./build.sh [-l //host.com/path/to/scripts/dir/] [-p] [-d]\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e       -l \u0026lt;URL\u0026gt;   The path under which the generated\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                  scripts will be deployed.\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e       -d         Disable obfuscating optimizations.\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2433140667124192106"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/chrome-frame-cfinstall"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3321550612614805569"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3321550612614805569"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3321550612614805569"}],"author":[{}],"sites$pageName":{"$t":"chrome-frame-cfinstall"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8020308428071002491"},"published":{"$t":"2014-04-07T14:20:23.792Z"},"updated":{"$t":"2014-04-07T14:20:23.817Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-07T14:20:23.792Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"ios_encoded_chrome_policy.plist"},"summary":{},"content":{"type":"text/xml","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8020308428071002491"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/920082191529537983"},{"rel":"alternate","type":"text/xml","href":"https://sites.google.com/a/chromium.org/dev/administrators/ios-mdm-policy-format/ios_encoded_chrome_policy.plist"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8020308428071002491"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8020308428071002491"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8020308428071002491"},{"rel":"edit-media","type":"text/xml","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8020308428071002491"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5541722979532347162"},"published":{"$t":"2014-04-07T14:20:22.403Z"},"updated":{"$t":"2014-04-07T14:20:22.431Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-07T14:20:22.403Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"ios_chrome_policy.plist"},"summary":{},"content":{"type":"audio/mpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5541722979532347162"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/920082191529537983"},{"rel":"alternate","type":"audio/mpeg","href":"https://sites.google.com/a/chromium.org/dev/administrators/ios-mdm-policy-format/ios_chrome_policy.plist"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5541722979532347162"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5541722979532347162"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5541722979532347162"},{"rel":"edit-media","type":"audio/mpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5541722979532347162"}],"author":[{"name":{"$t":"João da Silva"},"email":{"$t":"joaodasilva@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Xyl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1678239942978521145"},"published":{"$t":"2011-03-16T04:56:10.546Z"},"updated":{"$t":"2014-04-01T18:56:04.085Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-04-01T18:56:02.786Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Sync diagnostics"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-http:-go-aboutsync\" /\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\u003ca href\u003d\"http://go/aboutsync\" rel\u003d\"nofollow\"\u003ehttp://go/aboutsync\u003c/a\u003e\u003c/span\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h3\u003e\u003cul\u003e\u003cli\u003eLocated in \u003cb\u003eabout:sync\u003c/b\u003e (or \u003cb\u003echrome://sync-internals\u003c/b\u003e)\u003c/li\u003e\u003cli\u003eInspired by \u003cb\u003echrome://net-internals\u003c/b\u003e\u003c/li\u003e\u003cli\u003eIn M35 - Notifications tab has been branched off to \u003cb\u003echrome://invalidations\u003c/b\u003e.\u003c/li\u003e\u003cli\u003eTabs:\u003c/li\u003e\u003cul\u003e\u003cli\u003eAbout tab: \"Classic\" about:sync page, concise status overview\u003c/li\u003e\u003cli\u003eData tab: dump debugging data to text for copy \u0026amp; paste\u003c/li\u003e\u003cli\u003eNotifications tab: Keeps track of incoming sync notifications\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eEvents tab: logs for sync-related events\u003c/span\u003e\u003c/li\u003e\u003cli\u003eSync Node Browser tab: browse all synced data\u003c/li\u003e\u003cli\u003eSearch tab: Searching for strings in all synced data\u003c/li\u003e\u003cli\u003eTraffic tab: Text dump all of the sent and received messages to and from chrome sync servers.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-About-tab\" /\u003e\u003cb\u003eAbout tab\u003c/b\u003e\u003c/h3\u003e\u003cul\u003e\u003cli\u003e\"Classic\" about:sync page\u003c/li\u003e\u003cli\u003eUpdates on the fly\u003c/li\u003e\u003cul\u003e\u003cli\u003eTry moving a bookmark, or stopping and starting sync\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eSome stuff will eventually be moved out, but page is still useful as an overview\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Data-tab\" /\u003eData tab\u003c/h3\u003e\u003cul\u003e\u003cli\u003eDump to text button\u003c/li\u003e\u003cul\u003e\u003cli\u003eDumps all info from about and events tab\u003c/li\u003e\u003cul\u003e\u003cli\u003eBut can also select datatypes info to dump\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eCan be used to tell users to:\u003c/li\u003e\u003cul\u003e\u003cli\u003eOpen about:sync\u003c/li\u003e\u003cli\u003eRepro the problem if possible\u003c/li\u003e\u003cli\u003eWait a while (15-30 seconds)\u003c/li\u003e\u003cli\u003eGo to data tab\u003c/li\u003e\u003cli\u003eDump info, paste into bug (or email privately if there's sensitive info)\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eEvent log will probably be most useful part\u003c/li\u003e\u003cli\u003eRedacts sensitive info\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eRoom for improvement\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eAutomatically highlight dumped text, add \"Copy to clipboard\" button\u003c/span\u003e\u003c/li\u003e\u003cli\u003eButton to add to an existing bug, or create a new one\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Notifications-tab-up-to-M35-\" /\u003eNotifications tab (up to M35)\u003c/h3\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eIf a notification is received when the page (not just the tab) is open, a counter will increment (one for each data type)\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eTry moving a bookmark, setting a preference, or stopping and starting sync\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eTakes ~5-10 seconds for a notification to bounce back\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eTotal Count of invalidations per each data type\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eSession Counters reset if you reload\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eRoom for improvement\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eMore detailed connection stats\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eHow long has connection been up?  Which XMPP server/port?  How long ago was the last message sent/received?\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Events-tab\" /\u003eEvents tab\u003c/h3\u003e\u003cul\u003e\u003cli\u003eShows all sync events (i.e., functions in SyncManager::Observer and incoming notifications) that happen as long as the page is open\u003c/li\u003e\u003cul\u003e\u003cli\u003eTry moving a bookmark, or starting sync (dumps lots of data!)\u003c/li\u003e\u003cli\u003eDoesn't quite log everything yet\u003c/li\u003e\u003cli\u003eOnly logs events after backend is initialized\u003c/li\u003e\u003cli\u003eResets if you reload\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eRoom for improvement\u003c/li\u003e\u003cul\u003e\u003cli\u003eStore last N events (C++ side) so you can open it right when you hit a problem and still get some useful info\u003c/li\u003e\u003cli\u003eAlso log requests/responses to HTTP server\u003c/li\u003e\u003cli\u003ePerhaps more logging for sync setup events\u003c/li\u003e\u003cli\u003eBetter display (\u003ca href\u003d\"http://crbug.com/82866\"\u003e82866\u003c/a\u003e)\u003c/li\u003e\u003cli\u003eStart logging even before backend is initialized (tricky)\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Sync-node-browser-tab\" /\u003eSync node browser tab\u003c/h3\u003e\u003cul\u003e\u003cli\u003eShows sync nodes\u003c/li\u003e\u003cul\u003e\u003cli\u003eSync nodes are structured in a tree.\u003c/li\u003e\u003cli\u003eEach data type has a top-level node which is a child of the root node\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eOnly bookmarks sub-tree has true tree structure\u003c/span\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003eEverything else is just a list under the top-level node\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eUse links to navigate tree: parent, first child, predecessor, successor\u003c/li\u003e\u003cli\u003eIgnore specifics information for folder\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eTree view version\u003c/li\u003e\u003cul\u003e\u003cli\u003eTree visualized on the left, details of selected node on the right\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eDoes \u003ci\u003enot\u003c/i\u003e auto-update; you need to refresh\u003c/li\u003e\u003cul\u003e\u003cli\u003eBe careful, you may lose logged events; you can always open a new about:sync tab instead\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eRoom for improvement\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eImplement auto-updating (hard)\u003c/span\u003e\u003c/li\u003e\u003cli\u003eAdd a refresh button (easier)\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Search-tab\" /\u003eSearch tab\u003c/h3\u003e\u003cul\u003e\u003cli\u003eSearches expressions in all the nodes\u003c/li\u003e\u003cli\u003eSupports Regex over the JSONified version of each node\u003c/li\u003e\u003cli\u003eHas quick searches to provide for easy access to interesting nodes. So far:\u003c/li\u003e\u003cul\u003e\u003cli\u003eUnapplied updates\u003c/li\u003e\u003cli\u003eUnsynced items\u003c/li\u003e\u003cli\u003eDelted items\u003c/li\u003e\u003cli\u003eConflicted items (unapplied and unsynced)\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Network-level-debugging\" /\u003eNetwork-level debugging\u003c/h3\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eSync talks to the sync server via POSTing to clients4.google.com.\u003c/li\u003e\u003cli\u003eSync talks to the notification servers via XMPP (talk.google.com).\u003c/li\u003e\u003cli\u003eBoth sockets should show up in \u003cb\u003echrome://net-internals\u003c/b\u003e (after \u003ca href\u003d\"http://code.google.com/p/chromium/issues/detail?id\u003d82365\"\u003e82365\u003c/a\u003e is fixed).\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Room-for-improvement\" /\u003eRoom for improvement\u003c/h3\u003e\u003cul\u003e\u003cli\u003eData type-specific tabs\u003c/li\u003e\u003cul\u003e\u003cli\u003eModel associators / change processors have access to the ProfileSyncService, so shouldn't be too hard to emit events or reply to calls\u003c/li\u003e\u003cli\u003eProbably easier for things that live on the UI thread\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eSome way to capture VLOG() events\u003c/li\u003e\u003cli\u003eShould be obvious when sync isn't working\u003c/li\u003e\u003cli\u003eUse HTML notifications for events\u003c/li\u003e\u003cli\u003eFront-end for memory usage info (Lingesh is working on backend)\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/sync-diagnostics"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1678239942978521145"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1678239942978521145"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1678239942978521145"}],"author":[{"name":{"$t":"Fred Akalin"},"email":{"$t":"akalin@chromium.org"}}],"sites$pageName":{"$t":"sync-diagnostics"},"sites$revision":{"$t":"26"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5691184558880266088"},"published":{"$t":"2012-03-07T21:47:14.498Z"},"updated":{"$t":"2014-03-31T16:00:14.992Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-31T16:00:13.381Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Bluetooth Extension API"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;white-space:pre-wrap\"\u003eProposal Date\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eLast updated 2012-03-07\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eWho is the primary contact for this API?\u003c/span\u003e\u003cbr /\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cu\u003e\u003ca href\u003d\"mailto:keybuk@chromium.org\"\u003ekeybuk@chromium.org\u003c/a\u003e\u003c/u\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eWho will be responsible for this API? (Team please, not an individual)\u003c/span\u003e\u003cbr /\u003e\r\n\u003cp dir\u003d\"ltr\" style\u003d\"font-family:Verdana,sans-serif;font-weight:bold;margin-right:12pt;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003eApps Extension API Team\u003c/span\u003e\u003c/p\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eOverview\u003c/span\u003e\u003cbr /\u003e\r\n\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eA bluetooth API that is (eventually) \u003ci\u003eat least\u003c/i\u003e on par with the Android and iOS APIs. \u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:Arial;white-space:pre-wrap\"\u003eVersion 1 will support basic RFCOMM communication. Profile support will be left for a future version.\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eUse cases\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eThis API will allow extensions to communicate with bluetooth devices.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eDo you know anyone else, internal or external, that is also interested in this API?\u003c/span\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003eI'm not aware of anyone at this time.\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eCould this API be part of the web platform?\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eEventually, yes.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eDo you expect this API to be fairly stable?  How might it be extended or changed in the future?\u003c/span\u003e\u003cbr /\u003e\r\n\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eI expect the functionality proposed in this API to be stable. Additional functionality may be added in the future, but changes will be backwards-compatible.\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eList every UI surface belonging to or potentially affected by your API:\u003c/span\u003e\u003cbr /\u003e\r\n\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003eBluetooth Settings Panel.\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eHow could this API be abused?\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003e- bluetooth can be very resource intensive, causing battery drain for devices running extensions using this API\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eDescribe any concerns you have with exposing this API. Particular attention should be given to issues of security, privacy and performance.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eImagine you’re Dr. Evil Extension Writer, list the three worst evil deeds you could commit with your API (if you’ve got good ones, feel free to add more):\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e1) \u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e2) \u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;vertical-align:baseline;white-space:pre-wrap\"\u003e3) \u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eAlright Doctor, one last challenge:  \u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eCould a consumer of your API cause any permanent change to the user’s system using your API that would not be reversed when that consumer is removed from the system?\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eAnother main tenet of the Chrome Web Platform is that extensions and apps should “leave no trace” when they are removed.  If someone using your API could leave lasting changes, we need to know.\u003c/span\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eHow would you implement your desired features if this API didn't exist?\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eIt would be impossible.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-top:0px;margin-bottom:0px\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\u003cbr /\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eDraft API spec\u003c/span\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003ci\u003e\r\n\u003c/i\u003e\u003c/span\u003e\u003c/font\u003e\r\n\r\n\u003cdiv style\u003d\"font-family:Helvetica,Arial,sans-serif;font-size:small\"\u003e\r\n \u003cdiv style\u003d\"font-weight:normal;font-size:small\"\u003e\r\n \u003ch3 style\u003d\"margin-bottom:0px;font-size:17px;margin-top:1.5em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-MethodsacceptConnectionschrome.experimental.bluetooth.acceptConnections-string-uuid-stringservice_name-string-service_description-function-callback-Accept-incoming-bluetooth-connections-by-advertising-as-a-service.Parametersuuid-string-The-UUID-of-the-serv\" /\u003e\u003cdiv style\u003d\"font-weight:normal;font-size:small\"\u003e\u003ch3 style\u003d\"margin-bottom:0px;font-size:17px;margin-top:1.5em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Methods\" /\u003eMethods\u003c/h3\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-acceptConnections\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-acceptConnections\" /\u003eacceptConnections\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.acceptConnections(\u003cspan\u003estring \u003cvar\u003euuid\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, string\u003cvar\u003eservice_name\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, string \u003cvar\u003eservice_description\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eAccept incoming bluetooth connections by advertising as a service.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003euuid\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe UUID of the service being advertised.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eservice_name\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe human-readable name of the service being advertised.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eservice_description\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe human-readable description of the service being advertised.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled once for each connection that is established.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(BluetoothSocket result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003e\u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothSocket\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothSocket\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eA bluetooth socket identifier that can be used to communicate with the connected device.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-connect\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-connect\" /\u003econnect\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.connect(\u003cspan\u003eBluetoothDevice \u003cvar\u003edevice\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, string \u003cvar\u003euuid\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eConnect to a service on a bluetooth device.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters1\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003edevice\u003c/var\u003e \u003cem\u003e( \u003cspan\u003e\u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothDevice\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothDevice\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe target device of the connection.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003euuid\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe target service of the connection.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled when the connection is established.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function1\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(BluetoothSocket result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003e\u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothSocket\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothSocket\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eA bluetooth socket identifier that can be used to communicate with the connected device.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-disconnect\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-disconnect\" /\u003edisconnect\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.disconnect(\u003cspan\u003eBluetoothSocket \u003cvar\u003esocket\u003c/var\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(125,125,125)\"\u003e, function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eClose the bluetooth connection specified by socket.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters2\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003esocket\u003c/var\u003e \u003cem\u003e( \u003cspan\u003e\u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothSocket\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothSocket\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe bluetooth socket to read from.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan style\u003d\"color:rgb(125,125,125)\"\u003eoptional\u003c/span\u003e \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with a boolean value to indicate success.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function2\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eIf you specify the \u003cem\u003ecallback\u003c/em\u003e parameter, it should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(boolean result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if successful, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-getBluetoothAddress\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-getBluetoothAddress\" /\u003egetBluetoothAddress\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.getBluetoothAddress(\u003cspan\u003efunction \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eGet the bluetooth address of the system.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters3\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with the result.\u003c/dd\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function3\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(string result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe bluetooth address of the system.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-getDevicesWithService\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-getDevicesWithService\" /\u003egetDevicesWithService\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.getDevicesWithService(\u003cspan\u003estring \u003cvar\u003eservice_uuid\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eRequest a list of bluetooth devices that support service.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters4\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eservice_uuid\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe UUID of the desired service.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with a list of bluetooth devices.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function4\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(array of BluetoothDevice results) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresults\u003c/var\u003e \u003cem\u003e( \u003cspan\u003earray of \u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothDevice\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothDevice\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eAn array of BluetoothDevice objects, all of which provide the specified service.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-getOutOfBandPairingData\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-getOutOfBandPairingData\" /\u003egetOutOfBandPairingData\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.getOutOfBandPairingData(\u003cspan\u003efunction \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eGet the local Out of Band Pairing data.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters5\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with the Out of Band Pairing data.\u003c/dd\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function5\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(array of ArrayBuffer result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003earray of ArrayBuffer \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe local Out of Band Pairing data. The array will have length exactly 2 (or be null, in case of an error).\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-isBluetoothCapable\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-isBluetoothCapable\" /\u003eisBluetoothCapable\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.isBluetoothCapable(\u003cspan\u003efunction \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eCheck if this extension has access to bluetooth.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters6\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with the result.\u003c/dd\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function6\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(boolean result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if the extension has access to bluetooth, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-isBluetoothPowered\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-isBluetoothPowered\" /\u003eisBluetoothPowered\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.isBluetoothPowered(\u003cspan\u003efunction \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eCheck if the bluetooth adapter has power.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters7\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with the result.\u003c/dd\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function7\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(boolean result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if the bluetooth adapter has power, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-read\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-read\" /\u003eread\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.read(\u003cspan\u003eBluetoothSocket \u003cvar\u003esocket\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eRead data from a bluetooth connection.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters8\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003esocket\u003c/var\u003e \u003cem\u003e( \u003cspan\u003e\u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothSocket\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothSocket\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe bluetooth socket to read from.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled when data is available.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function8\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(ArrayBuffer result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eArrayBuffer \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eAn ArrayBuffer of data.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-setOutOfBandPairingData\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-setOutOfBandPairingData\" /\u003esetOutOfBandPairingData\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.setOutOfBandPairingData(\u003cspan\u003estring \u003cvar\u003ebluetooth_address\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, array of ArrayBuffer \u003cvar\u003edata\u003c/var\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(125,125,125)\"\u003e,function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eSet the Out of Band Pairing data for the bluetooth device at bluetooth_address.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters9\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ebluetooth_address\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe bluetooth address that is supplying the data.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003edata\u003c/var\u003e \u003cem\u003e( \u003cspan\u003earray of ArrayBuffer \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eAn array of length exactly equal to 2 containing the Out of Band Pairing data for the device at bluetooth_address.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan style\u003d\"color:rgb(125,125,125)\"\u003eoptional\u003c/span\u003e \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with a boolean value to indicate success.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function9\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eIf you specify the \u003cem\u003ecallback\u003c/em\u003e parameter, it should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(boolean result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if successful, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"method-write\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-write\" /\u003ewrite\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003echrome.experimental.bluetooth.write(\u003cspan\u003eBluetoothSocket \u003cvar\u003esocket\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, ArrayBuffer \u003cvar\u003edata\u003c/var\u003e\u003c/span\u003e\u003cspan\u003e, function \u003cvar\u003ecallback\u003c/var\u003e\u003c/span\u003e)\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eWrite data to a bluetooth connection.\u003c/p\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Parameters10\" /\u003eParameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003esocket\u003c/var\u003e \u003cem\u003e( \u003cspan\u003e\u003ca href\u003d\"experimental.bluetooth.html#type-BluetoothSocket\" style\u003d\"color:rgb(85,26,139)\"\u003eBluetoothSocket\u003c/a\u003e \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe bluetooth socket to read from.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003edata\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eArrayBuffer \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe data to be written.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ecallback\u003c/var\u003e \u003cem\u003e( \u003cspan\u003efunction \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eCalled with a boolean value to indicate success.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Callback-function10\" /\u003eCallback function\u003c/h4\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eThe callback \u003cem\u003eparameter\u003c/em\u003e should specify a function that looks like this:\u003c/p\u003e\u003cpre style\u003d\"color:rgb(0,112,0);font-size:9pt;background-color:rgb(250,250,250);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(187,187,187);border-right-color:rgb(187,187,187);border-bottom-color:rgb(187,187,187);border-left-color:rgb(187,187,187);margin-bottom:0px;padding-top:0.99em;padding-right:0.99em;padding-bottom:0.99em;padding-left:0.99em;word-wrap:break-word\"\u003efunction(boolean result) \u003cspan\u003e{...}\u003c/span\u003e;\u003c/pre\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eresult\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if successful, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-weight:normal;font-size:small\"\u003e\u003ca name\u003d\"types\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch3 style\u003d\"margin-bottom:0px;font-size:17px;margin-top:1.5em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Events\" /\u003eEvents\u003c/h3\u003e\u003cdiv style\u003d\"margin-bottom:2em;font-weight:normal;font-size:small\"\u003e\u003ca name\u003d\"event-onBluetoothAvailabilityChange\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-onBluetoothAvailabilityChange\" /\u003eonBluetoothAvailabilityChange\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003e\u003cspan style\u003d\"color:rgb(147,180,217)\"\u003echrome.experimental.bluetooth.\u003c/span\u003eonBluetoothAvailabilityChange\u003cspan style\u003d\"color:rgb(147,180,217)\"\u003e.addListener\u003c/span\u003e(function(boolean available) \u003cspan style\u003d\"color:rgb(147,180,217)\"\u003e{...}\u003c/span\u003e);\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eFired when the availability of bluetooth on the system changes.\u003c/p\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Listener-parameters\" /\u003eListener parameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eavailable\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if bluetooth is available, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em;font-weight:normal;font-size:small\"\u003e\u003ca name\u003d\"event-onBluetoothPoweredChange\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-onBluetoothPoweredChange\" /\u003eonBluetoothPoweredChange\u003c/h4\u003e\u003cdiv style\u003d\"border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;border-top-color:rgb(147,180,217);border-right-color:rgb(147,180,217);border-bottom-color:rgb(147,180,217);border-left-color:rgb(147,180,217);font-family:Courier New,courier,monospace;padding-top:0.5em;padding-right:0.5em;padding-bottom:0.5em;padding-left:2em;background-color:rgb(202,222,244);margin-top:1em\"\u003e\u003cspan style\u003d\"color:rgb(147,180,217)\"\u003echrome.experimental.bluetooth.\u003c/span\u003eonBluetoothPoweredChange\u003cspan style\u003d\"color:rgb(147,180,217)\"\u003e.addListener\u003c/span\u003e(function(boolean powered) \u003cspan style\u003d\"color:rgb(147,180,217)\"\u003e{...}\u003c/span\u003e);\u003c/div\u003e\u003cdiv style\u003d\"margin-left:2em\"\u003e\u003cp style\u003d\"margin-top:1em;margin-right:0px;margin-bottom:0px;margin-left:0px;line-height:16px\"\u003eFired when the powered state of bluetooth on the system changes.\u003c/p\u003e\u003cdiv\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Listener-parameters1\" /\u003eListener parameters\u003c/h4\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003epowered\u003c/var\u003e \u003cem\u003e( \u003cspan\u003eboolean \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eTrue if bluetooth is powered on, false otherwise.\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/h3\u003e\u003ch3 style\u003d\"margin-bottom:0px;font-size:17px;margin-top:1.5em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-Types\" /\u003eTypes\u003c/h3\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"type-BluetoothDevice\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-BluetoothDevice\" /\u003eBluetoothDevice\u003c/h4\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cem\u003e( \u003cspan\u003eobject \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eUsed to identify a specific bluetooth device to the system.\u003c/dd\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eaddress\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe address of the bluetooth device.\u003c/dd\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003ename\u003c/var\u003e \u003cem\u003e( \u003cspan\u003estring \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe name of the bluetooth device.\u003c/dd\u003e\u003c/div\u003e\u003c/dl\u003e\u003c/dd\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003ca name\u003d\"type-BluetoothSocket\" style\u003d\"color:rgb(0,0,204)\" /\u003e\u003ch4 style\u003d\"margin-bottom:0px;font-size:14px;margin-top:0.7em;margin-right:0px;margin-left:0px\"\u003e\u003ca name\u003d\"TOC-BluetoothSocket\" /\u003eBluetoothSocket\u003c/h4\u003e\u003cdiv\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cem\u003e( \u003cspan\u003eobject \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eUsed to identify a bluetooth socket to the system.\u003c/dd\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdt style\u003d\"font-weight:bold;margin-top:0.75em;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cvar\u003eid\u003c/var\u003e \u003cem\u003e( \u003cspan\u003einteger \u003c/span\u003e)\u003c/em\u003e\u003c/dt\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003eThe id of the socket.\u003c/dd\u003e\u003c/dl\u003e\u003c/dd\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-weight:normal;font-size:small\"\u003e\u003cdiv style\u003d\"margin-bottom:2em\"\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdd style\u003d\"margin-top:0.4em;margin-right:0px;margin-bottom:0.75em;margin-left:2em;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px\"\u003e\u003cdl style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;line-height:16px\"\u003e\u003cdd\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdl\u003e\r\n \u003c/dl\u003e\r\n \u003c/div\u003e\r\n \u003c/div\u003e\r\n \u003c/dd\u003e\r\n \u003c/dl\u003e\r\n \u003c/dd\u003e\r\n \u003c/dl\u003e\r\n \u003c/div\u003e\r\n \u003c/div\u003e\r\n\u003c/div\u003e\r\n\r\n\r\n\r\n\u003cspan style\u003d\"font-weight:bold;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eOpen questions\u003c/span\u003e\u003cbr /\u003e\r\n\u003cspan style\u003d\"font-family:Arial;font-weight:normal;font-style:italic;vertical-align:baseline;white-space:pre-wrap\"\u003eNote any unanswered questions that require further discussion.\u003c/span\u003e\u003c/div\u003e\r\n\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/333592083211368911"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/proposed-changes/apis-under-development/bluetooth-extension-api"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5691184558880266088"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4921463921044203350/4"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5691184558880266088"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5691184558880266088"}],"author":[{}],"sites$pageName":{"$t":"bluetooth-extension-api"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1044182605614349284"},"published":{"$t":"2014-03-28T23:04:59.044Z"},"updated":{"$t":"2014-03-28T23:04:59.091Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-28T23:04:59.044Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"wolf_wp.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1044182605614349284"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3997645127893838801"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/dell-chromebook-11/wolf_wp.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1044182605614349284"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1044182605614349284"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1044182605614349284"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1044182605614349284"}],"author":[{"name":{"$t":"Jean Zheng"},"email":{"$t":"jean@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5494536710288598376"},"published":{"$t":"2009-11-19T17:02:57.247Z"},"updated":{"$t":"2014-03-26T13:38:39.668Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-26T13:38:39.667Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Improving Build Times"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-make_chroot.sh\"\u003e\u003cstrong\u003e1 \u003c/strong\u003ecros_sdk\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-build_chrome.sh\"\u003e\u003cstrong\u003e2 \u003c/strong\u003ebuild_chrome.sh\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-build_platform_packages.sh\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ebuild_platform_packages.sh\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-build_kernel.sh\"\u003e\u003cstrong\u003e4 \u003c/strong\u003ebuild_kernel.sh\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-build_image.sh\"\u003e\u003cstrong\u003e5 \u003c/strong\u003ebuild_image.sh\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003eA Chromium-based OS can take a long time to build. However, you can perform many optimizations to speed up this process. Currently, the Chromium OS build system is driven by bash scripts that don't detect what items have changed. If you blindly use these scripts, you will be overbuilding and wasting precious time.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis page goes through each of the bash(or python) scripts, explaining what they do and when you have to run them. Another source of information is the -h option for each script.\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-make_local_repo.sh\" /\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-make_chroot.sh\" /\u003ecros_sdk\u003c/h2\u003e\r\n\u003cdiv\u003eThis script creates the local chroot environment using the a prebuilt SDK chroot and prebuilt packages. Use the \u003ccode\u003e--replace\u003c/code\u003e option to replace a previous chroot environment (re-running this command will not delete your previous chroot).  Once it has created the local chroot environment, \u003ccode\u003ecros_sdk\u003c/code\u003e will also chroot into the SDK and set up basic enviroment. If you prefer to just build and not enter, please use the \u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003e--download\u003c/span\u003e option. In terms of what you see, this is the development environment that all packages see when they are building. This script resides in chromite, but should be accessible in your PATH if you have recent enough depot_tools.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-build_chrome.sh\" /\u003ebuild_chrome.sh\u003c/h2\u003e\r\n\u003cdiv\u003eThis script builds your Chromium source for use with Chromium OS (special flags and environment changes are necessary for this to happen correctly). It then packages Chromium into a ZIP file that is used in build_image.sh. \u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThis script must be run outside of the chroot environment and needs to be re-run whenever major Chromium changes happen.  Since building Chromium takes a long time, unless you are making changes to Chromium, avoid syncing and rebuilding whenever possible. This script is based around the build process of Chromium and so it is more intelligent and will only build what is necessary. You can also test the resulting executable without running it on a Chromium OS system.  \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-enter_chroot.sh\" /\u003e\u003c/h2\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-build_platform_packages.sh\" /\u003ebuild_platform_packages.sh\u003c/h2\u003e\r\n\u003cdiv\u003eThis script does most of the building.  It runs through all the directories in third_party and under platform and runs their make_pkg.sh script. make_pkg.sh builds the .deb file for that package to be installed into the final Chromium OS image.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf you only make changes to one package, you only need to call its make_pkg.sh (from within chroot of course) and copy/install that deb to your Chromium OS device. This will save you a lot of time and prevent from having to rebuild the image every time. You will need to modify this script if you add any packages yourself.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-build_kernel.sh\" /\u003ebuild_kernel.sh\u003c/h2\u003e\r\n\u003cdiv\u003eThis scripts builds the kernel.\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-build_image.sh\" /\u003ebuild_image.sh\u003c/h2\u003e\r\n\u003cdiv\u003eBuilds the Chromium OS image. This script goes through all the packages in the ~/src/build/x86/local_packages and all the other packages listed in the prod text file in package_repo  to create the Chromium OS image.  The image is then placed under ~/src/build/images. From here you can convert the image to a VMWare image or install it to a USB drive.  \u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8945126227284375934"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/build/improving-build-times"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5494536710288598376"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5494536710288598376"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5494536710288598376"}],"author":[{}],"sites$pageName":{"$t":"improving-build-times"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"UCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5875603268063743574"},"published":{"$t":"2011-06-03T21:04:10.454Z"},"updated":{"$t":"2014-03-19T22:13:38.800Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-19T22:13:20.744Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Profiling in Chromium OS"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Setup\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eSetup\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Profiling-Autotests\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eProfiling Autotests\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Profiling-Standalone-Binaries\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eProfiling Standalone Binaries\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Generating-Profile-Reports\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eGenerating Profile Reports\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Bugs-\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eBugs?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003cp\u003e\u003cb\u003eWarning: The profiling infrastructure in Chromium OS is new and experimental. You may hit bugs. \u003cbr /\u003e\r\n\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eThe \u003ca href\u003d\"https://perf.wiki.kernel.org/index.php/Main_Page\" rel\u003d\"nofollow\"\u003eperf_events\u003c/a\u003e (aka perf) profiling tools can be used to collect profiles in Chromium OS. This page describes how to run perf on standalone programs, or on autotests.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Setup\" /\u003eSetup\u003cbr /\u003e\r\n\u003c/h2\u003e\r\n\u003cp\u003e\u003ccode\u003edev-utils/perf\u003c/code\u003e should be installed by default in the chroot host (NOTE: it may be in /usr/local/sbin instead of /usr/sbin):\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ /usr/sbin/perf --version\u003cbr /\u003e\r\nperf version 2.6.38.1720.g564bb7e\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eIt should also be installed by default on the target board when building a developer image for Chromium OS. If it isn't, you can emerge it manually:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ sudo emerge-${BOARD} perf\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eSome things to note:\u003c/p\u003e\r\n\u003col\u003e\u003cli\u003eYou should also make sure you have debug symbols in the chroot, ideally for all packages. Otherwise perf report will not show function names. Debug symbols are installed by default when you emerge a package. Look in \u003ccode\u003e/build/${BOARD}/usr/lib/debug\u003c/code\u003e. \u003c/li\u003e\r\n\u003cli\u003eThe build-id of the debug symbols must match the binaries installed on the Chromium OS device, otherwise the reports will be inaccurate. This could happen if you re-emerge a package without copying it onto the device which you are profiling on.\u003c/li\u003e\r\n\u003cli\u003eThe version of perf you are using is tied to the kernel version. If you use kernel-9999, use perf-9999. If you use kernel-next, use perf-next. Otherwise your results wont be reliable.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Profiling-Autotests\" /\u003eProfiling Autotests\u003c/h2\u003e\r\n\u003cp\u003eProfiling autotests can be done using run_remote_tests.sh. There are two options you should be interested in:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e  --profiler: What profiler to use? Example: cros_perf.\u003cbr /\u003e\r\n  --profiler_args: Arguments to pass to the profiler. Example: options\u003d\\\"-e instructions -g\\\"\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eFor example, to get a profile of AesThroughput using the default perf options, simply do:\u003cbr /\u003e\r\n\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ ./run_remote_tests.sh --remote\u003d172.18.221.163 AesThroughput --profiler\u003dcros_perf\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nThe perf data file will be placed in the autotest results directory when the test completes:\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e\u0026gt;\u0026gt;\u0026gt; Details stored under /tmp/run_remote_tests.WBFE\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e$ ls /tmp/run_remote_tests.WBFE/platform_AesThroughput/platform_AesThroughput/profiling/iteration.1/     \u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003eperf.data\u003c/code\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\nYou can also pass custom arguments to perf. E.g. to collect instruction events and call graph information:\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ ./run_remote_tests.sh --remote\u003d172.18.221.163 AesThroughput --profile --profiler_args\u003d\"options\u003d\\\"-e instructions -g\\\"\"\u003cbr /\u003e\r\n\u003c/code\u003e\u003c/div\u003e\r\n\u003cbr /\u003e\r\nSome things to note:\u003cbr /\u003e\r\n\u003col\u003e\u003cli\u003eBy default this collects system-wide profiles, which is usually what you want. You can filter by thread id or binary when you produce the report.\u003c/li\u003e\r\n\u003cli\u003eperf is invoked immediately prior to the autotest run_once() method and is killed immediately after the method completes. Everything executed in this method will be included in the profile.\u003cbr /\u003e\r\n\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Profiling-Standalone-Binaries\" /\u003eProfiling Standalone Binaries\u003cbr /\u003e\r\n\u003c/h2\u003e\r\n\u003cp\u003eSSH to your Chromium OS device and run\u003ccode\u003e perf record\u003c/code\u003e:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ sudo perf record -g -a -e cycles -- sleep 5\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e[ perf record: Woken up 1 times to write data ]\u003c/code\u003e\u003cbr /\u003e\r\n\u003ccode\u003e[ perf record: Captured and wrote 0.186 MB perf.data (~8115 samples) ]\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eYou can replace sleep with any binary you want to profile. Use\u003ccode\u003e perf help record\u003c/code\u003e to see the various options for recording data.\u003c/p\u003e\r\n\u003cp\u003eNow copy the data file back to your chroot:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ scp chronos@chromeos-box:/tmp/perf.data .\u003c/code\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Generating-Profile-Reports\" /\u003eGenerating Profile Reports\u003c/h2\u003e\r\n\u003cp\u003eUse \u003ccode\u003eperf report\u003c/code\u003e to display the profile:\u003c/p\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ /usr/sbin/perf report -i perf.data --symfs /build/${BOARD}/ --kallsyms /build/${BOARD}/boot/System.map-3.3.0\u003c/code\u003e\u003c/div\u003e\r\n\u003cp\u003eYou can pass --tui for a more interactive interface (buggy), or --stdio for text output. Use \u003ccode\u003eperf help report\u003c/code\u003e to see the various options for reporting data. \u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Bugs-\" /\u003eBugs?\u003c/h2\u003e\r\n\u003cp\u003eFile it: \u003ca href\u003d\"https://code.google.com/p/chromium/issues/entry?template\u003dDefect%20on%20Chrome%20OS\"\u003ehttp://crbug.com/new\u003c/a\u003e, cc: sonnyrao.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/593897542665142458"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/profiling-in-chromeos"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5875603268063743574"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5875603268063743574"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5875603268063743574"}],"author":[{"name":{"$t":"Raymes Khoury"},"email":{"$t":"raymes@chromium.org"}}],"sites$pageName":{"$t":"profiling-in-chromeos"},"sites$revision":{"$t":"19"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2881464308779388089"},"published":{"$t":"2014-03-18T22:46:41.922Z"},"updated":{"$t":"2014-03-18T22:46:41.922Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-18T22:46:41.922Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#listitem","label":"listitem"}],"title":{"$t":""},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7582987878577786924"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2881464308779388089"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2881464308779388089"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2881464308779388089"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$revision":{"$t":"1"},"gs$field":[{"index":"A","name":"Brand \u0026 Model Number","$t":"Asus Eee PC 1005HG"},{"index":"B","name":"Wifi","$t":"OK"},{"index":"C","name":"Ethernet","$t":""},{"index":"D","name":"Trackpad","$t":""},{"index":"E","name":"Suspend/Resume","$t":"on"},{"index":"F","name":"Comments \u0026 Caveats","$t":""},{"index":"G","name":"Contact","$t":""},{"index":"H","name":"Buy Link","$t":""}]},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6940895886748314293"},"published":{"$t":"2014-03-18T16:52:12.894Z"},"updated":{"$t":"2014-03-18T16:52:12.925Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-18T16:52:12.894Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"tracing-frame-viewer.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6940895886748314293"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/tracing-frame-viewer.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6940895886748314293"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6940895886748314293"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6940895886748314293"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6940895886748314293"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1739524752740988861"},"published":{"$t":"2014-03-18T16:51:52.302Z"},"updated":{"$t":"2014-03-18T16:51:52.343Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-18T16:51:52.302Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"tracing-scheduler.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1739524752740988861"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/tracing-scheduler.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1739524752740988861"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1739524752740988861"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1739524752740988861"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1739524752740988861"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7899378988021581665"},"published":{"$t":"2014-03-18T16:51:24.314Z"},"updated":{"$t":"2014-03-18T16:51:24.341Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-18T16:51:24.314Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"tracing-flow.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7899378988021581665"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/tracing-flow.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7899378988021581665"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7899378988021581665"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7899378988021581665"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7899378988021581665"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/703588318794963666"},"published":{"$t":"2014-03-18T16:50:50.742Z"},"updated":{"$t":"2014-03-18T16:50:50.773Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-18T16:50:50.742Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"tracing-systrace.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/703588318794963666"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5276382689810110447"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/recording-tracing-runs/tracing-systrace.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/703588318794963666"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/703588318794963666"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/703588318794963666"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/703588318794963666"}],"author":[{"name":{"$t":"Sami Kyöstilä"},"email":{"$t":"skyostil@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9142841046817220102"},"published":{"$t":"2009-05-18T04:55:18.159Z"},"updated":{"$t":"2014-03-14T23:02:35.668Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-14T23:02:34.640Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Version Numbers"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Chromium\" /\u003eChromium\u003c/h2\u003e\r\n\r\n\u003cp\u003eChromium version numbers consist of 4 parts: MAJOR.MINOR.BUILD.PATCH.\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eMAJOR and MINOR \u003cb\u003emay\u003c/b\u003e get updated with any significant Google Chrome release (Beta or Stable update). MAJOR \u003cb\u003emust\u003c/b\u003e get updated for any backwards incompatible user data change (since this data survives updates). \u003c/li\u003e\r\n\u003cli\u003eBUILD \u003cb\u003emust\u003c/b\u003e get updated whenever a release candidate is built from the current trunk (at least weekly for Dev channel release candidates). The BUILD number is an ever-increasing number representing a point in time of the Chromium trunk.\u003c/li\u003e\r\n\u003cli\u003ePATCH \u003cb\u003emust\u003c/b\u003e get updated whenever a release candidate is built from the BUILD branch.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eMAJOR and MINOR track updates to the Google Chrome stable channel. In this sense, they reflect a scheduling or marketing decision rather than anything about the code itself. These numbers are generally only significant for tracking milestones. In the event that we get a significant release vehicle for Chromium code \u003cb\u003eother\u003c/b\u003e than Google Chrome, we can revisit the versioning scheme.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eThe BUILD and PATCH numbers together are the canonical representation of what code is in a given release.\u003c/b\u003e The BUILD number is always increasing as the source code trunk advances, so build 180 is always newer code than build 177. The PATCH number is always increasing for a given BUILD. Developers and testers generally refer to an instance of the product (Chromium or Google Chrome) as BUILD.PATCH. It is the shortest unambiguous name for a build.\u003c/p\u003e\r\n\u003cp\u003eFor example, the 154 branch was originally released as 0.3.154.9, but now stands at 1.0.154.65. It's the same basic code with a lot of bug fixes applied. The fact that it went from a Beta release to several 1.0 stable releases just reflects the decision to call some version (1.0.154.36) 'out of Beta'.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Chromium-OS\" /\u003eChromium OS\u003c/h2\u003e\r\n\u003cp\u003eStarting with the R16 release, we standardized on the following: [Chrome Version.]\u0026lt;TIP_BUILD\u0026gt;.\u0026lt;BRANCH_BUILD\u0026gt;.\u0026lt;BRANCH_BRANCH_BUILD\u0026gt;\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eThe Chromium version is implicit.  On the R25 branch, Chromium OS will be using Chromium version 25.\u003c/li\u003e\r\n\u003cli\u003eTIP_BUILD will be updated every time the canaries run on the tip of tree (trunk/master in various VCS schemas).  This is typically done every 6 hours.  The number increases monotonically.\u003c/li\u003e\r\n\u003cli\u003eBRANCH_BUILD will be updated every time a new build is started on a branch.  This happens whenever a commit is made to the branch.\u003c/li\u003e\r\n\u003cli\u003eBRANCH_BRANCH_BUILD is used when a branch of a branch is made.  This is a bit uncommon, but has happened.  It follows the same rules as BRANCH_BUILD.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eAn example Chromium OS version string:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eVersion 25.0.1364.126\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThis is the Chromium version (see previous section for details)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cli\u003ePlatform 3428.193.0 (Official Build) stable-channel stumpy\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eThis was branched from the tip of tree (ToT) when it was at 3428.0.0.  It is the 193rd build on that branch.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Coordinating-Versions\" /\u003eCoordinating Versions\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Chromium-Chromium-OS\" /\u003eChromium \u0026amp; Chromium OS\u003c/h4\u003e\r\n\u003cp\u003eAll releases of Chromium OS are tagged in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/manifest-versions/+/master/paladin/buildspecs/\"\u003echromiumos/manifest-versions.git\u003c/a\u003e repository. You can look up a Chromium version by doing:\u003c/p\u003e\u003cul\u003e\u003cli\u003efind the buildspec for the specific version you're interested in\u003c/li\u003e\u003cul\u003e\u003cli\u003ee.g. 5636.0.0-rc1.xml\u003c/li\u003e\u003c/ul\u003e\u003cli\u003elook up the git sha1 for the \u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003echromiumos-overlay repo in it\u003c/span\u003e\u003cul\u003e\u003cli\u003ee.g. 4670dbea357617d1fc09db88829b71d8eb1f82e2\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003elook at the chromeos-base/chromeos-chrome/ subdir of that repo at that revision\u003c/li\u003e\u003cul\u003e\u003cli\u003ee.g. \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/4670dbea357617d1fc09db88829b71d8eb1f82e2/chromeos-base/chromeos-chrome/\"\u003echromeos-base/chromeos-chrome\u003c/a\u003e contains version 35.0.1891.2\u003c/li\u003e\u003cli\u003ee.g. \u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"2\"\u003egit ls-files \u003c/font\u003e4670dbea357617d1fc09db88829b71d8eb1f82e2\u003cfont size\u003d\"2\"\u003e chromeos-base/chromeos-chrome/\u003c/font\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Chrome-Chrome-OS\" /\u003eChrome \u0026amp; Chrome OS\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eYou can use the online \u003ca href\u003d\"http://cros-omahaproxy.appspot.com/\"\u003eCrOS-OmahaProxy\u003c/a\u003e app engine to see what versions of Chrome shipped in which versions of Chrome OS.\u003c/p\u003e\r\n\u003cp\u003eAlternatively, all releases of Chrome are tagged in the \u003cspan style\u003d\"background-color:transparent\"\u003e\u003ca href\u003d\"https://chrome-internal.googlesource.com/chromeos/manifest-versions/+/master/buildspecs/\"\u003echromeos/manifest-versions.git\u003c/a\u003e repository. Follow the same steps as above w/Chromium.\u003c/span\u003e\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/version-numbers"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9142841046817220102"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9142841046817220102"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9142841046817220102"}],"author":[{"name":{"$t":"Mark Larson"},"email":{"$t":"mal@chromium.org"}}],"sites$pageName":{"$t":"version-numbers"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2804847210463903911"},"published":{"$t":"2010-05-06T00:01:35.350Z"},"updated":{"$t":"2014-03-14T13:28:14.158Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-14T13:28:12.718Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Submitting Patches"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cpre\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-Get-Your-Change-Into-the-Linux-Kernel\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eHow to Get Your Change Into the Linux Kernel\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Care-And-Operation-Of-Your-Linus-Torvalds\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eCare And Operation Of Your Linus Torvalds\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-SECTION-1---CREATING-AND-SENDING-YOUR-CHANGE\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eSECTION 1 - CREATING AND SENDING YOUR CHANGE\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1-diff--up-\"\u003e\u003cstrong\u003e2.1.1 \u003c/strong\u003e1) \"diff -up\"\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2-Describe-your-changes.\"\u003e\u003cstrong\u003e2.1.2 \u003c/strong\u003e2) Describe your changes.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3-Separate-your-changes.\"\u003e\u003cstrong\u003e2.1.3 \u003c/strong\u003e3) Separate your changes.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4-Style-check-your-changes.\"\u003e\u003cstrong\u003e2.1.4 \u003c/strong\u003e4) Style check your changes.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5-Select-e-mail-destination.\"\u003e\u003cstrong\u003e2.1.5 \u003c/strong\u003e5) Select e-mail destination.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6-Select-your-CC-e-mail-carbon-copy-list.\"\u003e\u003cstrong\u003e2.1.6 \u003c/strong\u003e6) Select your CC (e-mail carbon copy) list.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-7-No-MIME-no-links-no-compression-no-attachments.-Just-plain-text.\"\u003e\u003cstrong\u003e2.1.7 \u003c/strong\u003e7) No MIME, no links, no compression, no attachments. Just plain text.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-8-E-mail-size.\"\u003e\u003cstrong\u003e2.1.8 \u003c/strong\u003e8) E-mail size.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-9-Name-your-kernel-version.\"\u003e\u003cstrong\u003e2.1.9 \u003c/strong\u003e9) Name your kernel version.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-10-Don-t-get-discouraged.-Re-submit.\"\u003e\u003cstrong\u003e2.1.10 \u003c/strong\u003e10) Don't get discouraged. Re-submit.\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-11-Include-PATCH-in-the-subject\"\u003e\u003cstrong\u003e2.1.11 \u003c/strong\u003e11) Include PATCH in the subject\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-12-Sign-your-work\"\u003e\u003cstrong\u003e2.1.12 \u003c/strong\u003e12) Sign your work\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-13-When-to-use-Acked-by:-and-Cc:\"\u003e\u003cstrong\u003e2.1.13 \u003c/strong\u003e13) When to use Acked-by: and Cc:\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-14-Using-Reported-by:-Tested-by:-Reviewed-by:-and-Suggested-by:\"\u003e\u003cstrong\u003e2.1.14 \u003c/strong\u003e14) Using Reported-by:, Tested-by:, Reviewed-by: and Suggested-by:\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-15-The-canonical-patch-format\"\u003e\u003cstrong\u003e2.1.15 \u003c/strong\u003e15) The canonical patch format\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-16-Sending-git-pull-requests-from-Linus-emails-\"\u003e\u003cstrong\u003e2.1.16 \u003c/strong\u003e16) Sending \"git pull\" requests (from Linus emails)\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-SECTION-2---HINTS-TIPS-AND-TRICKS\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003eSECTION 2 - HINTS, TIPS, AND TRICKS\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1-Read-Documentation-CodingStyle\"\u003e\u003cstrong\u003e2.2.1 \u003c/strong\u003e1) Read Documentation/CodingStyle\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2-ifdefs-are-ugly\"\u003e\u003cstrong\u003e2.2.2 \u003c/strong\u003e2) #ifdefs are ugly\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3-static-inline-is-better-than-a-macro\"\u003e\u003cstrong\u003e2.2.3 \u003c/strong\u003e3) 'static inline' is better than a macro\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4-Don-t-over-design.\"\u003e\u003cstrong\u003e2.2.4 \u003c/strong\u003e4) Don't over-design.\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-SECTION-3---REFERENCES\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003eSECTION 3 - REFERENCES\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-Get-Your-Change-Into-the-Linux-Kernel\" /\u003e\tHow to Get Your Change Into the Linux Kernel\u003c/h2\u003e\t\tor\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Care-And-Operation-Of-Your-Linus-Torvalds\" /\u003e\tCare And Operation Of Your Linus Torvalds\u003c/h2\u003e\r\n\r\n\r\nFor a person or company who wishes to submit a change to the Linux\r\nkernel, the process can sometimes be daunting if you're not familiar\r\nwith \"the system.\" This text is a collection of suggestions which\r\ncan greatly increase the chances of your change being accepted.\r\n\r\nRead Documentation/SubmitChecklist for a list of items to check\r\nbefore submitting code. If you are submitting a driver, also read\r\nDocumentation/SubmittingDrivers.\r\n\r\n\r\n\r\n--------------------------------------------\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-SECTION-1---CREATING-AND-SENDING-YOUR-CHANGE\" /\u003eSECTION 1 - CREATING AND SENDING YOUR CHANGE\u003c/h3\u003e--------------------------------------------\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-1-diff--up-\" /\u003e1) \"diff -up\"\u003c/h4\u003e------------\r\n\r\nUse \"diff -up\" or \"diff -uprN\" to create patches.\r\n\r\nAll changes to the Linux kernel occur in the form of patches, as\r\ngenerated by diff(1). When creating your patch, make sure to create it\r\nin \"unified diff\" format, as supplied by the '-u' argument to diff(1).\r\nAlso, please use the '-p' argument which shows which C function each\r\nchange is in - that makes the resultant diff a lot easier to read.\r\nPatches should be based in the root kernel source directory,\r\nnot in any lower subdirectory.\r\n\r\nTo create a patch for a single file, it is often sufficient to do:\r\n\r\n\tSRCTREE\u003d linux-2.6\r\n\tMYFILE\u003d drivers/net/mydriver.c\r\n\r\n\tcd $SRCTREE\r\n\tcp $MYFILE $MYFILE.orig\r\n\tvi $MYFILE\t# make your change\r\n\tcd ..\r\n\tdiff -up $SRCTREE/$MYFILE{.orig,} \u0026gt; /tmp/patch\r\n\r\nTo create a patch for multiple files, you should unpack a \"vanilla\",\r\nor unmodified kernel source tree, and generate a diff against your\r\nown source tree. For example:\r\n\r\n\tMYSRC\u003d /devel/linux-2.6\r\n\r\n\ttar xvfz linux-2.6.12.tar.gz\r\n\tmv linux-2.6.12 linux-2.6.12-vanilla\r\n\tdiff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \\\r\n\t\tlinux-2.6.12-vanilla $MYSRC \u0026gt; /tmp/patch\r\n\r\n\"dontdiff\" is a list of files which are generated by the kernel during\r\nthe build process, and should be ignored in any diff(1)-generated\r\npatch. The \"dontdiff\" file is included in the kernel tree in\r\n2.6.12 and later.\r\n\r\nMake sure your patch does not include any extra files which do not\r\nbelong in a patch submission. Make sure to review your patch -after-\r\ngenerated it with diff(1), to ensure accuracy.\r\n\r\nIf your changes produce a lot of deltas, you may want to look into\r\nsplitting them into individual patches which modify things in\r\nlogical stages. This will facilitate easier reviewing by other\r\nkernel developers, very important if you want your patch accepted.\r\nThere are a number of scripts which can aid in this:\r\n\r\nQuilt:\r\nhttp://savannah.nongnu.org/projects/quilt\r\n\r\nAndrew Morton's patch scripts:\r\nhttp://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz\r\nInstead of these scripts, quilt is the recommended patch management\r\ntool (see above).\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-2-Describe-your-changes.\" /\u003e2) Describe your changes.\u003c/h4\u003eDescribe the technical detail of the change(s) your patch includes.\r\n\r\nBe as specific as possible. The WORST descriptions possible include\r\nthings like \"update driver X\", \"bug fix for driver X\", or \"this patch\r\nincludes updates for subsystem X. Please apply.\"\r\n\r\nThe maintainer will thank you if you write your patch description in a\r\nform which can be easily pulled into Linux's source code management\r\nsystem, git, as a \"commit log\". See #15, below.\r\n\r\nIf your description starts to get long, that's a sign that you probably\r\nneed to split up your patch. See #3, next.\r\n\r\nWhen you submit or resubmit a patch or patch series, include the\r\ncomplete patch description and justification for it. Don't just\r\nsay that this is version N of the patch (series). Don't expect the\r\npatch merger to refer back to earlier patch versions or referenced\r\nURLs to find the patch description and put that into the patch.\r\nI.e., the patch (series) and its description should be self-contained.\r\nThis benefits both the patch merger(s) and reviewers. Some reviewers\r\nprobably didn't even receive earlier versions of the patch.\r\n\r\nIf the patch fixes a logged bug entry, refer to that bug entry by\r\nnumber and URL.\r\n\r\nIf you want to refer to a specific commit, don't just refer to the\r\nSHA-1 ID of the commit. Please also include the oneline summary of\r\nthe commit, to make it easier for reviewers to know what it is about.\r\nExample:\r\n\r\n\tCommit e21d2170f36602ae2708 (\"video: remove unnecessary\r\n\tplatform_set_drvdata()\") removed the unnecessary\r\n\tplatform_set_drvdata(), but left the variable \"dev\" unused,\r\n\tdelete it.\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-3-Separate-your-changes.\" /\u003e3) Separate your changes.\u003c/h4\u003eSeparate _logical changes_ into a single patch file.\r\n\r\nFor example, if your changes include both bug fixes and performance\r\nenhancements for a single driver, separate those changes into two\r\nor more patches. If your changes include an API update, and a new\r\ndriver which uses that new API, separate those into two patches.\r\n\r\nOn the other hand, if you make a single change to numerous files,\r\ngroup those changes into a single patch. Thus a single logical change\r\nis contained within a single patch.\r\n\r\nIf one patch depends on another patch in order for a change to be\r\ncomplete, that is OK. Simply note \"this patch depends on patch X\"\r\nin your patch description.\r\n\r\nIf you cannot condense your patch set into a smaller set of patches,\r\nthen only post say 15 or so at a time and wait for review and integration.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-4-Style-check-your-changes.\" /\u003e4) Style check your changes.\u003c/h4\u003eCheck your patch for basic style violations, details of which can be\r\nfound in Documentation/CodingStyle. Failure to do so simply wastes\r\nthe reviewers time and will get your patch rejected, probably\r\nwithout even being read.\r\n\r\nAt a minimum you should check your patches with the patch style\r\nchecker prior to submission (scripts/checkpatch.pl). You should\r\nbe able to justify all violations that remain in your patch.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-5-Select-e-mail-destination.\" /\u003e5) Select e-mail destination.\u003c/h4\u003eLook through the MAINTAINERS file and the source code, and determine\r\nif your change applies to a specific subsystem of the kernel, with\r\nan assigned maintainer. If so, e-mail that person. The script\r\nscripts/get_maintainer.pl can be very useful at this step.\r\n\r\nIf no maintainer is listed, or the maintainer does not respond, send\r\nyour patch to the primary Linux kernel developer's mailing list,\r\nlinux-kernel@vger.kernel.org. Most kernel developers monitor this\r\ne-mail list, and can comment on your changes.\r\n\r\n\r\nDo not send more than 15 patches at once to the vger mailing lists!!!\r\n\r\n\r\nLinus Torvalds is the final arbiter of all changes accepted into the\r\nLinux kernel. His e-mail address is . \r\nHe gets a lot of e-mail, so typically you should do your best to -avoid-\r\nsending him e-mail. \r\n\r\nPatches which are bug fixes, are \"obvious\" changes, or similarly\r\nrequire little discussion should be sent or CC'd to Linus. Patches\r\nwhich require discussion or do not have a clear advantage should\r\nusually be sent first to linux-kernel. Only after the patch is\r\ndiscussed should the patch then be submitted to Linus.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-6-Select-your-CC-e-mail-carbon-copy-list.\" /\u003e6) Select your CC (e-mail carbon copy) list.\u003c/h4\u003eUnless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org.\r\n\r\nOther kernel developers besides Linus need to be aware of your change,\r\nso that they may comment on it and offer code review and suggestions.\r\nlinux-kernel is the primary Linux kernel developer mailing list.\r\nOther mailing lists are available for specific subsystems, such as\r\nUSB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the\r\nMAINTAINERS file for a mailing list that relates specifically to\r\nyour change.\r\n\r\nMajordomo lists of VGER.KERNEL.ORG at:\r\n\t\r\n\r\nIf changes affect userland-kernel interfaces, please send\r\nthe MAN-PAGES maintainer (as listed in the MAINTAINERS file)\r\na man-pages patch, or at least a notification of the change,\r\nso that some information makes its way into the manual pages.\r\n\r\nEven if the maintainer did not respond in step #5, make sure to ALWAYS\r\ncopy the maintainer when you change their code.\r\n\r\nFor small patches you may want to CC the Trivial Patch Monkey\r\ntrivial@kernel.org which collects \"trivial\" patches. Have a look\r\ninto the MAINTAINERS file for its current manager.\r\nTrivial patches must qualify for one of the following rules:\r\n Spelling fixes in documentation\r\n Spelling fixes which could break grep(1)\r\n Warning fixes (cluttering with useless warnings is bad)\r\n Compilation fixes (only if they are actually correct)\r\n Runtime fixes (only if they actually fix things)\r\n Removing use of deprecated functions/macros (eg. check_region)\r\n Contact detail and documentation fixes\r\n Non-portable code replaced by portable code (even in arch-specific,\r\n since people copy, as long as it's trivial)\r\n Any fix by the author/maintainer of the file (ie. patch monkey\r\n in re-transmission mode)\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-7-No-MIME-no-links-no-compression-no-attachments.-Just-plain-text.\" /\u003e7) No MIME, no links, no compression, no attachments. Just plain text.\u003c/h4\u003eLinus and other kernel developers need to be able to read and comment\r\non the changes you are submitting. It is important for a kernel\r\ndeveloper to be able to \"quote\" your changes, using standard e-mail\r\ntools, so that they may comment on specific portions of your code.\r\n\r\nFor this reason, all patches should be submitting e-mail \"inline\".\r\nWARNING: Be wary of your editor's word-wrap corrupting your patch,\r\nif you choose to cut-n-paste your patch.\r\n\r\nDo not attach the patch as a MIME attachment, compressed or not.\r\nMany popular e-mail applications will not always transmit a MIME\r\nattachment as plain text, making it impossible to comment on your\r\ncode. A MIME attachment also takes Linus a bit more time to process,\r\ndecreasing the likelihood of your MIME-attached change being accepted.\r\n\r\nException: If your mailer is mangling patches then someone may ask\r\nyou to re-send them using MIME.\r\n\r\nSee Documentation/email-clients.txt for hints about configuring\r\nyour e-mail client so that it sends your patches untouched.\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-8-E-mail-size.\" /\u003e8) E-mail size.\u003c/h4\u003eWhen sending patches to Linus, always follow step #7.\r\n\r\nLarge changes are not appropriate for mailing lists, and some\r\nmaintainers. If your patch, uncompressed, exceeds 300 kB in size,\r\nit is preferred that you store your patch on an Internet-accessible\r\nserver, and provide instead a URL (link) pointing to your patch.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-9-Name-your-kernel-version.\" /\u003e9) Name your kernel version.\u003c/h4\u003eIt is important to note, either in the subject line or in the patch\r\ndescription, the kernel version to which this patch applies.\r\n\r\nIf the patch does not apply cleanly to the latest kernel version,\r\nLinus will not apply it.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-10-Don-t-get-discouraged.-Re-submit.\" /\u003e10) Don't get discouraged. Re-submit.\u003c/h4\u003eAfter you have submitted your change, be patient and wait. If Linus\r\nlikes your change and applies it, it will appear in the next version\r\nof the kernel that he releases.\r\n\r\nHowever, if your change doesn't appear in the next version of the\r\nkernel, there could be any number of reasons. It's YOUR job to\r\nnarrow down those reasons, correct what was wrong, and submit your\r\nupdated change.\r\n\r\nIt is quite common for Linus to \"drop\" your patch without comment.\r\nThat's the nature of the system. If he drops your patch, it could be\r\ndue to\r\n* Your patch did not apply cleanly to the latest kernel version.\r\n* Your patch was not sufficiently discussed on linux-kernel.\r\n* A style issue (see section 2).\r\n* An e-mail formatting issue (re-read this section).\r\n* A technical problem with your change.\r\n* He gets tons of e-mail, and yours got lost in the shuffle.\r\n* You are being annoying.\r\n\r\nWhen in doubt, solicit comments on linux-kernel mailing list.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-11-Include-PATCH-in-the-subject\" /\u003e11) Include PATCH in the subject\u003c/h4\u003eDue to high e-mail traffic to Linus, and to linux-kernel, it is common\r\nconvention to prefix your subject line with [PATCH]. This lets Linus\r\nand other kernel developers more easily distinguish patches from other\r\ne-mail discussions.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-12-Sign-your-work\" /\u003e12) Sign your work\u003c/h4\u003eTo improve tracking of who did what, especially with patches that can\r\npercolate to their final resting place in the kernel through several\r\nlayers of maintainers, we've introduced a \"sign-off\" procedure on\r\npatches that are being emailed around.\r\n\r\nThe sign-off is a simple line at the end of the explanation for the\r\npatch, which certifies that you wrote it or otherwise have the right to\r\npass it on as an open-source patch. The rules are pretty simple: if you\r\ncan certify the below:\r\n\r\n Developer's Certificate of Origin 1.1\r\n\r\n By making a contribution to this project, I certify that:\r\n\r\n (a) The contribution was created in whole or in part by me and I\r\n have the right to submit it under the open source license\r\n indicated in the file; or\r\n\r\n (b) The contribution is based upon previous work that, to the best\r\n of my knowledge, is covered under an appropriate open source\r\n license and I have the right under that license to submit that\r\n work with modifications, whether created in whole or in part\r\n by me, under the same open source license (unless I am\r\n permitted to submit under a different license), as indicated\r\n in the file; or\r\n\r\n (c) The contribution was provided directly to me by some other\r\n person who certified (a), (b) or (c) and I have not modified\r\n it.\r\n\r\n\t(d) I understand and agree that this project and the contribution\r\n\t are public and that a record of the contribution (including all\r\n\t personal information I submit with it, including my sign-off) is\r\n\t maintained indefinitely and may be redistributed consistent with\r\n\t this project or the open source license(s) involved.\r\n\r\nthen you just add a line saying\r\n\r\n\tSigned-off-by: Random J Developer \r\n\r\nusing your real name (sorry, no pseudonyms or anonymous contributions.)\r\n\r\nSome people also put extra tags at the end. They'll just be ignored for\r\nnow, but you can do this to mark internal company procedures or just\r\npoint out some special detail about the sign-off. \r\n\r\nIf you are a subsystem or branch maintainer, sometimes you need to slightly\r\nmodify patches you receive in order to merge them, because the code is not\r\nexactly the same in your tree and the submitters'. If you stick strictly to\r\nrule (c), you should ask the submitter to rediff, but this is a totally\r\ncounter-productive waste of time and energy. Rule (b) allows you to adjust\r\nthe code, but then it is very impolite to change one submitter's code and\r\nmake him endorse your bugs. To solve this problem, it is recommended that\r\nyou add a line between the last Signed-off-by header and yours, indicating\r\nthe nature of your changes. While there is nothing mandatory about this, it\r\nseems like prepending the description with your mail and/or name, all\r\nenclosed in square brackets, is noticeable enough to make it obvious that\r\nyou are responsible for last-minute changes. Example :\r\n\r\n\tSigned-off-by: Random J Developer \r\n\t[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]\r\n\tSigned-off-by: Lucky K Maintainer \r\n\r\nThis practise is particularly helpful if you maintain a stable branch and\r\nwant at the same time to credit the author, track changes, merge the fix,\r\nand protect the submitter from complaints. Note that under no circumstances\r\ncan you change the author's identity (the From header), as it is the one\r\nwhich appears in the changelog.\r\n\r\nSpecial note to back-porters: It seems to be a common and useful practise\r\nto insert an indication of the origin of a patch at the top of the commit\r\nmessage (just after the subject line) to facilitate tracking. For instance,\r\nhere's what we see in 2.6-stable :\r\n\r\n Date: Tue May 13 19:10:30 2008 +0000\r\n\r\n SCSI: libiscsi regression in 2.6.25: fix nop timer handling\r\n\r\n commit 4cf1043593db6a337f10e006c23c69e5fc93e722 upstream\r\n\r\nAnd here's what appears in 2.4 :\r\n\r\n Date: Tue May 13 22:12:27 2008 +0200\r\n\r\n wireless, airo: waitbusy() won't delay\r\n\r\n [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]\r\n\r\nWhatever the format, this information provides a valuable help to people\r\ntracking your trees, and to people trying to trouble-shoot bugs in your\r\ntree.\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-13-When-to-use-Acked-by:-and-Cc:\" /\u003e13) When to use Acked-by: and Cc:\u003c/h4\u003eThe Signed-off-by: tag indicates that the signer was involved in the\r\ndevelopment of the patch, or that he/she was in the patch's delivery path.\r\n\r\nIf a person was not directly involved in the preparation or handling of a\r\npatch but wishes to signify and record their approval of it then they can\r\narrange to have an Acked-by: line added to the patch's changelog.\r\n\r\nAcked-by: is often used by the maintainer of the affected code when that\r\nmaintainer neither contributed to nor forwarded the patch.\r\n\r\nAcked-by: is not as formal as Signed-off-by:. It is a record that the acker\r\nhas at least reviewed the patch and has indicated acceptance. Hence patch\r\nmergers will sometimes manually convert an acker's \"yep, looks good to me\"\r\ninto an Acked-by:.\r\n\r\nAcked-by: does not necessarily indicate acknowledgement of the entire patch.\r\nFor example, if a patch affects multiple subsystems and has an Acked-by: from\r\none subsystem maintainer then this usually indicates acknowledgement of just\r\nthe part which affects that maintainer's code. Judgement should be used here.\r\nWhen in doubt people should refer to the original discussion in the mailing\r\nlist archives.\r\n\r\nIf a person has had the opportunity to comment on a patch, but has not\r\nprovided such comments, you may optionally add a \"Cc:\" tag to the patch.\r\nThis is the only tag which might be added without an explicit action by the\r\nperson it names. This tag documents that potentially interested parties\r\nhave been included in the discussion\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-14-Using-Reported-by:-Tested-by:-Reviewed-by:-and-Suggested-by:\" /\u003e14) Using Reported-by:, Tested-by:, Reviewed-by: and Suggested-by:\u003c/h4\u003eIf this patch fixes a problem reported by somebody else, consider adding a\r\nReported-by: tag to credit the reporter for their contribution. Please\r\nnote that this tag should not be added without the reporter's permission,\r\nespecially if the problem was not reported in a public forum. That said,\r\nif we diligently credit our bug reporters, they will, hopefully, be\r\ninspired to help us again in the future.\r\n\r\nA Tested-by: tag indicates that the patch has been successfully tested (in\r\nsome environment) by the person named. This tag informs maintainers that\r\nsome testing has been performed, provides a means to locate testers for\r\nfuture patches, and ensures credit for the testers.\r\n\r\nReviewed-by:, instead, indicates that the patch has been reviewed and found\r\nacceptable according to the Reviewer's Statement:\r\n\r\n\tReviewer's statement of oversight\r\n\r\n\tBy offering my Reviewed-by: tag, I state that:\r\n\r\n \t (a) I have carried out a technical review of this patch to\r\n\t evaluate its appropriateness and readiness for inclusion into\r\n\t the mainline kernel.\r\n\r\n\t (b) Any problems, concerns, or questions relating to the patch\r\n\t have been communicated back to the submitter. I am satisfied\r\n\t with the submitter's response to my comments.\r\n\r\n\t (c) While there may be things that could be improved with this\r\n\t submission, I believe that it is, at this time, (1) a\r\n\t worthwhile modification to the kernel, and (2) free of known\r\n\t issues which would argue against its inclusion.\r\n\r\n\t (d) While I have reviewed the patch and believe it to be sound, I\r\n\t do not (unless explicitly stated elsewhere) make any\r\n\t warranties or guarantees that it will achieve its stated\r\n\t purpose or function properly in any given situation.\r\n\r\nA Reviewed-by tag is a statement of opinion that the patch is an\r\nappropriate modification of the kernel without any remaining serious\r\ntechnical issues. Any interested reviewer (who has done the work) can\r\noffer a Reviewed-by tag for a patch. This tag serves to give credit to\r\nreviewers and to inform maintainers of the degree of review which has been\r\ndone on the patch. Reviewed-by: tags, when supplied by reviewers known to\r\nunderstand the subject area and to perform thorough reviews, will normally\r\nincrease the likelihood of your patch getting into the kernel.\r\n\r\nA Suggested-by: tag indicates that the patch idea is suggested by the person\r\nnamed and ensures credit to the person for the idea. Please note that this\r\ntag should not be added without the reporter's permission, especially if the\r\nidea was not posted in a public forum. That said, if we diligently credit our\r\nidea reporters, they will, hopefully, be inspired to help us again in the\r\nfuture.\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-15-The-canonical-patch-format\" /\u003e15) The canonical patch format\u003c/h4\u003eThe canonical patch subject line is:\r\n\r\n Subject: [PATCH 001/123] subsystem: summary phrase\r\n\r\nThe canonical patch message body contains the following:\r\n\r\n - A \"from\" line specifying the patch author.\r\n\r\n - An empty line.\r\n\r\n - The body of the explanation, which will be copied to the\r\n permanent changelog to describe this patch.\r\n\r\n - The \"Signed-off-by:\" lines, described above, which will\r\n also go in the changelog.\r\n\r\n - A marker line containing simply \"---\".\r\n\r\n - Any additional comments not suitable for the changelog.\r\n\r\n - The actual patch (diff output).\r\n\r\nThe Subject line format makes it very easy to sort the emails\r\nalphabetically by subject line - pretty much any email reader will\r\nsupport that - since because the sequence number is zero-padded,\r\nthe numerical and alphabetic sort is the same.\r\n\r\nThe \"subsystem\" in the email's Subject should identify which\r\narea or subsystem of the kernel is being patched.\r\n\r\nThe \"summary phrase\" in the email's Subject should concisely\r\ndescribe the patch which that email contains. The \"summary\r\nphrase\" should not be a filename. Do not use the same \"summary\r\nphrase\" for every patch in a whole patch series (where a \"patch\r\nseries\" is an ordered sequence of multiple, related patches).\r\n\r\nBear in mind that the \"summary phrase\" of your email becomes a\r\nglobally-unique identifier for that patch. It propagates all the way\r\ninto the git changelog. The \"summary phrase\" may later be used in\r\ndeveloper discussions which refer to the patch. People will want to\r\ngoogle for the \"summary phrase\" to read discussion regarding that\r\npatch. It will also be the only thing that people may quickly see\r\nwhen, two or three months later, they are going through perhaps\r\nthousands of patches using tools such as \"gitk\" or \"git log\r\n--oneline\".\r\n\r\nFor these reasons, the \"summary\" must be no more than 70-75\r\ncharacters, and it must describe both what the patch changes, as well\r\nas why the patch might be necessary. It is challenging to be both\r\nsuccinct and descriptive, but that is what a well-written summary\r\nshould do.\r\n\r\nThe \"summary phrase\" may be prefixed by tags enclosed in square\r\nbrackets: \"Subject: [PATCH tag] \". The tags are not\r\nconsidered part of the summary phrase, but describe how the patch\r\nshould be treated. Common tags might include a version descriptor if\r\nthe multiple versions of the patch have been sent out in response to\r\ncomments (i.e., \"v1, v2, v3\"), or \"RFC\" to indicate a request for\r\ncomments. If there are four patches in a patch series the individual\r\npatches may be numbered like this: 1/4, 2/4, 3/4, 4/4. This assures\r\nthat developers understand the order in which the patches should be\r\napplied and that they have reviewed or applied all of the patches in\r\nthe patch series.\r\n\r\nA couple of example Subjects:\r\n\r\n Subject: [patch 2/5] ext2: improve scalability of bitmap searching\r\n Subject: [PATCHv2 001/207] x86: fix eflags tracking\r\n\r\nThe \"from\" line must be the very first line in the message body,\r\nand has the form:\r\n\r\n From: Original Author \r\n\r\nThe \"from\" line specifies who will be credited as the author of the\r\npatch in the permanent changelog. If the \"from\" line is missing,\r\nthen the \"From:\" line from the email header will be used to determine\r\nthe patch author in the changelog.\r\n\r\nThe explanation body will be committed to the permanent source\r\nchangelog, so should make sense to a competent reader who has long\r\nsince forgotten the immediate details of the discussion that might\r\nhave led to this patch. Including symptoms of the failure which the\r\npatch addresses (kernel log messages, oops messages, etc.) is\r\nespecially useful for people who might be searching the commit logs\r\nlooking for the applicable patch. If a patch fixes a compile failure,\r\nit may not be necessary to include _all_ of the compile failures; just\r\nenough that it is likely that someone searching for the patch can find\r\nit. As in the \"summary phrase\", it is important to be both succinct as\r\nwell as descriptive.\r\n\r\nThe \"---\" marker line serves the essential purpose of marking for patch\r\nhandling tools where the changelog message ends.\r\n\r\nOne good use for the additional comments after the \"---\" marker is for\r\na diffstat, to show what files have changed, and the number of\r\ninserted and deleted lines per file. A diffstat is especially useful\r\non bigger patches. Other comments relevant only to the moment or the\r\nmaintainer, not suitable for the permanent changelog, should also go\r\nhere. A good example of such comments might be \"patch changelogs\"\r\nwhich describe what has changed between the v1 and v2 version of the\r\npatch.\r\n\r\nIf you are going to include a diffstat after the \"---\" marker, please\r\nuse diffstat options \"-p 1 -w 70\" so that filenames are listed from\r\nthe top of the kernel source tree and don't use too much horizontal\r\nspace (easily fit in 80 columns, maybe with some indentation).\r\n\r\nSee more details on the proper patch format in the following\r\nreferences.\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-16-Sending-git-pull-requests-from-Linus-emails-\" /\u003e16) Sending \"git pull\" requests (from Linus emails)\u003c/h4\u003ePlease write the git repo address and branch name alone on the same line\r\nso that I can't even by mistake pull from the wrong branch, and so\r\nthat a triple-click just selects the whole thing.\r\n\r\nSo the proper format is something along the lines of:\r\n\r\n\t\"Please pull from\r\n\r\n\t\tgit://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus\r\n\r\n\t to get these changes:\"\r\n\r\nso that I don't have to hunt-and-peck for the address and inevitably\r\nget it wrong (actually, I've only gotten it wrong a few times, and\r\nchecking against the diffstat tells me when I get it wrong, but I'm\r\njust a lot more comfortable when I don't have to \"look for\" the right\r\nthing to pull, and double-check that I have the right branch-name).\r\n\r\n\r\nPlease use \"git diff -M --stat --summary\" to generate the diffstat:\r\nthe -M enables rename detection, and the summary enables a summary of\r\nnew/deleted or renamed files.\r\n\r\nWith rename detection, the statistics are rather different [...]\r\nbecause git will notice that a fair number of the changes are renames.\r\n\r\n-----------------------------------\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-SECTION-2---HINTS-TIPS-AND-TRICKS\" /\u003eSECTION 2 - HINTS, TIPS, AND TRICKS\u003c/h3\u003e-----------------------------------\r\n\r\nThis section lists many of the common \"rules\" associated with code\r\nsubmitted to the kernel. There are always exceptions... but you must\r\nhave a really good reason for doing so. You could probably call this\r\nsection Linus Computer Science 101.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-1-Read-Documentation-CodingStyle\" /\u003e1) Read Documentation/CodingStyle\u003c/h4\u003eNuff said. If your code deviates too much from this, it is likely\r\nto be rejected without further review, and without comment.\r\n\r\nOne significant exception is when moving code from one file to\r\nanother -- in this case you should not modify the moved code at all in\r\nthe same patch which moves it. This clearly delineates the act of\r\nmoving the code and your changes. This greatly aids review of the\r\nactual differences and allows tools to better track the history of\r\nthe code itself.\r\n\r\nCheck your patches with the patch style checker prior to submission\r\n(scripts/checkpatch.pl). The style checker should be viewed as\r\na guide not as the final word. If your code looks better with\r\na violation then its probably best left alone.\r\n\r\nThe checker reports at three levels:\r\n - ERROR: things that are very likely to be wrong\r\n - WARNING: things requiring careful review\r\n - CHECK: things requiring thought\r\n\r\nYou should be able to justify all violations that remain in your\r\npatch.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-2-ifdefs-are-ugly\" /\u003e2) #ifdefs are ugly\u003c/h4\u003eCode cluttered with ifdefs is difficult to read and maintain. Don't do\r\nit. Instead, put your ifdefs in a header, and conditionally define\r\n'static inline' functions, or macros, which are used in the code.\r\nLet the compiler optimize away the \"no-op\" case.\r\n\r\nSimple example, of poor code:\r\n\r\n\tdev \u003d alloc_etherdev (sizeof(struct funky_private));\r\n\tif (!dev)\r\n\t\treturn -ENODEV;\r\n\t#ifdef CONFIG_NET_FUNKINESS\r\n\tinit_funky_net(dev);\r\n\t#endif\r\n\r\nCleaned-up example:\r\n\r\n(in header)\r\n\t#ifndef CONFIG_NET_FUNKINESS\r\n\tstatic inline void init_funky_net (struct net_device *d) {}\r\n\t#endif\r\n\r\n(in the code itself)\r\n\tdev \u003d alloc_etherdev (sizeof(struct funky_private));\r\n\tif (!dev)\r\n\t\treturn -ENODEV;\r\n\tinit_funky_net(dev);\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-3-static-inline-is-better-than-a-macro\" /\u003e3) 'static inline' is better than a macro\u003c/h4\u003eStatic inline functions are greatly preferred over macros.\r\nThey provide type safety, have no length limitations, no formatting\r\nlimitations, and under gcc they are as cheap as macros.\r\n\r\nMacros should only be used for cases where a static inline is clearly\r\nsuboptimal [there are a few, isolated cases of this in fast paths],\r\nor where it is impossible to use a static inline function [such as\r\nstring-izing].\r\n\r\n'static inline' is preferred over 'static __inline__', 'extern inline',\r\nand 'extern __inline__'.\r\n\r\n\r\n\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-4-Don-t-over-design.\" /\u003e4) Don't over-design.\u003c/h4\u003eDon't try to anticipate nebulous future cases which may or may not\r\nbe useful: \"Make it as simple as you can, and no simpler.\"\r\n\r\n\r\n\r\n----------------------\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-SECTION-3---REFERENCES\" /\u003eSECTION 3 - REFERENCES\u003c/h3\u003e----------------------\r\n\r\nAndrew Morton, \"The perfect patch\" (tpp).\r\n \r\n\r\nJeff Garzik, \"Linux kernel patch submission format\".\r\n \r\n\r\nGreg Kroah-Hartman, \"How to piss off a kernel subsystem maintainer\".\r\n \r\n \r\n \r\n \r\n \r\n\r\nNO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!\r\n \r\n\r\nKernel Documentation/CodingStyle:\r\n \r\n\r\nLinus Torvalds's mail on the canonical patch format:\r\n \r\n\r\nAndi Kleen, \"On submitting kernel patches\"\r\n Some strategies to get difficult or controversial changes in.\r\n http://halobates.de/on-submitting-patches.pdf\r\n\r\n--\r\n\u003c/pre\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7097299014995540955"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/chromium-os-kernel/submitting-patches"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2804847210463903911"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2804847210463903911"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2804847210463903911"}],"author":[{}],"sites$pageName":{"$t":"submitting-patches"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1137529411414143876"},"published":{"$t":"2014-03-13T21:40:38.751Z"},"updated":{"$t":"2014-03-13T21:40:38.779Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-13T21:40:38.751Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"EditingUI.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1137529411414143876"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6360596036256815927"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/password-generation/EditingUI.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1137529411414143876"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1137529411414143876"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1137529411414143876"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1137529411414143876"}],"author":[{"name":{"$t":"Garrett Casto"},"email":{"$t":"gcasto@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1706461791334486448"},"published":{"$t":"2014-03-13T21:10:53.051Z"},"updated":{"$t":"2014-03-13T21:10:53.088Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-13T21:10:53.051Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"GenerationUI.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1706461791334486448"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6360596036256815927"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/password-generation/GenerationUI.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1706461791334486448"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1706461791334486448"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1706461791334486448"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1706461791334486448"}],"author":[{"name":{"$t":"Garrett Casto"},"email":{"$t":"gcasto@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"Wyl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8079158040642616494"},"published":{"$t":"2011-07-06T18:08:53.141Z"},"updated":{"$t":"2014-03-11T23:28:00.249Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-11T23:27:58.690Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Breaking Changes"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eOur general philosophy for the Chrome extensions system is to try hard to avoid breaking (ie backwards-incompatible) changes. Over time we've discussed a number of ideas for improvements based on actual experience with the extensions system that would require breaking backwards compatibility. Ideally we'd do them all together in one big batch to minimize developer pain.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIn no particular order, here's a list of these ideas. Some require changes to the manifest format, and some change the behavior of existing APIs.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eWe want to reduce the need for background pages to help save memory, and some ideas for how to do this require breaking changes. See \u003ca href\u003d\"http://code.google.com/p/chromium/issues/list?q\u003dTaskForce%3DBackgroundPagesMustDie\" target\u003d\"_blank\"\u003ea list of related bugs\u003c/a\u003e. \u003c/li\u003e\u003cli\u003eSplit out host permissions and API permissions into separate fields (\u003ca href\u003d\"http://crbug.com/62898\"\u003ecrbug.com/62898\u003c/a\u003e)\u003c/li\u003e\u003cul\u003e\u003cli\u003eWe might want to design for extensibility in these fields, for example to allow things like adding an optional \"why\"/\"justification\" field for each permission.\u003c/li\u003e\u003cli\u003eAlso, for some API's such as spell checking, you want to grant permissions at the host level to get events on input into text boxes but don't necessarily want the ability to do cross-origin XHR or chrome.tabs.executeScript.\u003c/li\u003e\u003cul\u003e\u003cli\u003e(aa says:) In that case, the permission should be different. A host permission means authenticated access to the host. We shouldn't twist the meaning per-API.\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cli\u003eImprove security in content scripts by either forcing the following behaviors, or making them the default with explicit developer opt-out:\u003c/li\u003e\u003cul\u003e\u003cli\u003eforbid eval\u003c/li\u003e\u003cli\u003eturn on javascript strict mode (\u003ca href\u003d\"https://developer.mozilla.org/en/JavaScript/Strict_mode\" rel\u003d\"nofollow\"\u003ehttps://developer.mozilla.org/en/JavaScript/Strict_mode\u003c/a\u003e)\u003c/li\u003e\u003cli\u003eturn on CSP  (\u003ca href\u003d\"http://www.w3.org/Security/wiki/Content_Security_Policy\" rel\u003d\"nofollow\"\u003ehttp://www.w3.org/Security/wiki/Content_Security_Policy\u003c/a\u003e)\u003c/li\u003e\u003cli\u003eIf a content script injects a \u0026lt;script\u0026gt; tag into the DOM, only allow it if the src is an https url\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eSplit permissions into read and write (Context: captureVisibleTab really requires \u0026lt;all_urls\u0026gt; because iframes can have content from any site, but we don't want to require screenshot extensions to get write-all permissions when they don't need/want it. There may be other cases like this.)\u003c/li\u003e\u003cli\u003eMove tabs.captureVisibleTab into its own top-level permission to simplify concerns with iframe permissions\u003c/li\u003e\u003cli\u003eRationalize naming conventions. Excepting special circumstances, we probably want to stick to the \u003ca href\u003d\"http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml\" target\u003d\"_blank\"\u003eGoogle javascript style guide\u003c/a\u003e:\u003c/li\u003e\u003cul\u003e\u003cli\u003efunctionNamesLikeThis, variableNamesLikeThis, ClassNamesLikeThis, EnumNamesLikeThis, methodNamesLikeThis, and SYMBOLIC_CONSTANTS_LIKE_THIS\u003c/li\u003e\u003cli\u003eUnify our handling for abbreviations like URL - we have functions named getURL, setUpdateUrlData, addUrl, etc. We should standardize on URL or Url. \u003c/li\u003e\u003c/ul\u003e\u003cli\u003eHave a \"tabs_simple\" or \"tabs_light\" permission for things like chrome.tabs.{create,update,remove,onRemoved}\u003c/li\u003e\u003cli\u003eAllow extensions to have opt-in \"public\" pages that can be loaded in iframes, window.open, etc. from within other origins, and make pages private by default.\u003c/li\u003e\u003cli\u003eFix the port madness in URLPattern. Can we make all URLPatterns support ports? I believe right now, most cases of URLPatterns make ports an error, which means we can make it work without a breaking change. But in a few cases, ports are silently allowed for backward compatibility. Fixing this would be the breaking change.\u003c/li\u003e\u003cli\u003eChange chrome://favicon/ to a new scheme chrome-favicon:// (this was the root of a security bug, \u003ca href\u003d\"http://crbug.com/83010\"\u003ehttp://crbug.com/83010\u003c/a\u003e)\u003c/li\u003e\u003cul\u003e\u003cli\u003eWe should just make this a separate top-level API permission. We don't need or want authenticated access to these origins - we just want the icons.\u003c/li\u003e\u003cli\u003eSome work on this is in-progress: crbug.com/172375\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eAllow better URL pattern matching (to differentiate between path, query and fragments): \u003ca href\u003d\"http://crbug.com/84024\"\u003ehttp://crbug.com/84024\u003c/a\u003e\u003c/li\u003e\u003cli\u003eChange the manifest format in any ways needed to let us use \u003ca href\u003d\"http://json-schema.org/\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eJSON Schema\u003c/a\u003e for parsing it.\u003c/li\u003e\u003cul\u003e\u003cli\u003eNote: we already have an internal C++ implementation of JSON Schema that is used for other things in the extension system\u003c/li\u003e\u003c/ul\u003e\u003cli\u003eScan extension.cc for DEPRECATED and the like. Remove old stuff like the support for multiple pageActions.\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/361818175711938067"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/extensions/proposed-changes/extension-system-changes/breaking-changes"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8079158040642616494"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8079158040642616494"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8079158040642616494"}],"author":[{"name":{"$t":"Antony Sargent"},"email":{"$t":"asargent@chromium.org"}}],"sites$pageName":{"$t":"breaking-changes"},"sites$revision":{"$t":"22"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4792326093440491263"},"published":{"$t":"2012-10-22T19:46:59.790Z"},"updated":{"$t":"2014-03-11T01:02:05.758Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-11T01:02:05.742Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"bashrc-tail"},"summary":{},"content":{"type":"application/x-shellscript","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4792326093440491263"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8862287037771446359"},{"rel":"alternate","type":"application/x-shellscript","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/-quickly-building-for-cros-arm-x64/bashrc-tail"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4792326093440491263"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4792326093440491263"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4792326093440491263"},{"rel":"edit-media","type":"application/x-shellscript","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4792326093440491263"}],"author":[{"name":{"$t":"Ami Fischman"},"email":{"$t":"fischman@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7341579603503221812"},"published":{"$t":"2014-03-06T02:43:56.652Z"},"updated":{"$t":"2014-03-06T02:52:56.859Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-06T02:52:56.841Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Selection.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7341579603503221812"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9001020975767722444"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/how-tos/trace-event-profiling-tool/trace-event-reading/Selection.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7341579603503221812"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7341579603503221812"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7341579603503221812"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7341579603503221812"}],"author":[{"name":{"$t":"Fadi Meawad"},"email":{"$t":"fmeawad@chromium.org"}}],"sites$revision":{"$t":"3"}},{"gd$etag":"\"Xyl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5961792032638489271"},"published":{"$t":"2010-06-16T01:26:03.777Z"},"updated":{"$t":"2014-03-03T02:31:38.350Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-03-03T02:31:37.225Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Overview of Native Client for ARM"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cp\u003eThis page has moved to the \u003ca href\u003d\"http://developer.chrome.com/native-client/reference/sandbox_internals/arm-32-bit-sandbox\"\u003eNative Client ARM 32-bit Sandbox\u003c/a\u003e.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6566195967208808905"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/reference/arm-overview"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5961792032638489271"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5961792032638489271"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5961792032638489271"}],"author":[{}],"sites$pageName":{"$t":"arm-overview"},"sites$revision":{"$t":"26"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/961859338472891362"},"published":{"$t":"2014-02-28T01:24:23.274Z"},"updated":{"$t":"2014-02-28T01:24:23.303Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-28T01:24:23.274Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"2014 Chrome OS Firmware Summit- Chrome EC.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/961859338472891362"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/2014%20Chrome%20OS%20Firmware%20Summit-%20Chrome%20EC.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/961859338472891362"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/961859338472891362"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/961859338472891362"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/961859338472891362"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"WSl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4135472737682618275"},"published":{"$t":"2010-09-12T05:01:09.597Z"},"updated":{"$t":"2014-02-26T02:17:38.537Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2011-06-02T22:11:20.213Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"SAFT"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-4\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Theory-of-operation\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eTheory of operation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Running-SAFT\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eRunning SAFT\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Tests-implemented-so-far\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eTests implemented so far\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Enhancing-SAFT\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eEnhancing SAFT\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Interpreting-SAFT-errors\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eInterpreting SAFT errors\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Theory-of-operation\" /\u003eTheory of operation\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSAFT stands for Semi Automated Firmware Test. It is a Python and BASH based Linux application enabled in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os\"\u003eChromeOS\u003c/a\u003e test distribution. On the target system SAFT code is placed in \u003ccode\u003e/usr/sbin/firmware/saft\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e. The source code is controlled by a separate \u003ca href\u003d\"goog_880557684\"\u003egit\u003c/a\u003e\u003c/font\u003e\u003c/code\u003e\u003ca href\u003d\"goog_880557684\"\u003e \u003c/a\u003e\u003ccode\u003e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003ca href\u003d\"http://gerrit.chromium.org/gerrit/gitweb?p\u003dchromiumos%2Fplatform%2Fsaft.git;a\u003dshortlog;h\u003dHEAD\"\u003erepository\u003c/a\u003e. \u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSAFT is designed to verify BIOS functionality, including different aspects of \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified Boot\u003c/a\u003e and \u003ca href\u003d\"https://docs.google.com/a/google.com/Doc?docid\u003d0AbUTgMyqR_XeZGRuaDd4OXdfODJkbTRjZzJjdA\u0026amp;hl\u003den\" target\u003d\"_blank\"\u003eGoogle Chrome OS Firmware - High Level Specification\u003c/a\u003e. To test this thoroughly multiple system restarts are needed, some including booting in recovery mode. This is why \u003cb\u003eSAFT requires the flash drive to be present on the system under test\u003c/b\u003e, both to keep state between reboots and to provide recovery mode boot medium. Recovery mode boot requires operator involvement (unplugging and plugging in the flash drive), which makes SAFT a 'semi automated' test. SAFT is meant to be run by the firmware vendors, and is required to be easy to set up and run.  This is why it is not using the autotest framework, all what's needed is a target netbook and a flash memory stick.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe Chrome OS root file system is immutable, so there is a need to enable or disable SAFT execution without modifying the root fs contents. The SAFT \u003ca href\u003d\"http://upstart.ubuntu.com/getting-started.html\" rel\u003d\"nofollow\"\u003eupstart\u003c/a\u003e script \u003ccode\u003e/etc/init/saft.conf\u003c/code\u003e is executed on every reboot. It checks if the flash drive is present, and a \"follow up\" script \u003ccode\u003e/var/saft.sh\u003c/code\u003e exists on it. If the follow up script does not exist, SAFT execution terminates, if it does exist, the follow up script is invoked. This allows to enable/disable SAFT execution without modifying the root file system.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWhen SAFT is not running, the upstart script terminates after logging the state in \u003ccode\u003e/tmp/saft.conf\u003c/code\u003e:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003e\u003ccode\u003elocalhost ~ # cat /tmp/saft.log\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eFound sdc after 0 seconds\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eNo SAFT in progress\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eTo enable SAFT execution on a system, the 'follow up' script is created and the system is reset. On the next and all following startups until the 'follow up' script is deleted, SAFT application is invoked.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSAFT needs some means of representing the target boot state (what firmware and kernel were used, what was the reason for reboot, where the root file system is hosted, etc.). A so called boot state vector is used for that, which is a string described as follows in the source code:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eThe string has a form of x:x:x:\u0026lt;removable\u0026gt;:\u0026lt;partition_number\u0026gt;, where x' represent contents of the appropriate BINF files as reported by ACPI, \u0026lt;removable\u0026gt; is set to 1 or 0 depending if the root device is removable or not, and \u0026lt;partition number\u0026gt; is the last element of the root device name, designating the partition where the root fs is mounted. \u003c/code\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003ccode\u003eThis vector fully describes the way the system came up.\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv\u003eWhen executed on start up, the 'follow up' script creates the necessary environment and starts the actual SAFT Python application located in\u003ccode\u003e \u0026lt;flash drive mount point\u0026gt;/usr/sbin/firmware/saft/saft_utility.py\u003c/code\u003e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e. This application is a state machine, where\u003c/font\u003e e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003each state introduces a unique defect in the system (corrupted firmware or kernel, different CGPT attributes, etc., etc.).\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIn each step the application checks if the current boot state vector matches the expected state, and if so corrects the previously introduced defect, introduces the next one and reboots again. This continues until all steps are passed, provided every state is processed properly. If SAFT application detects that the target state vector does not match the expected state, it terminates immediately. \u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003eThe sequence of defect introducing actions is stored in the \u003ccode style\u003d\"color:rgb(0,96,0)\"\u003esaft_utility.py:\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:monospace;font-size:medium;white-space:pre-wrap\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003eTEST_STATE_SEQUENCE\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:monospace;font-size:medium;white-space:pre-wrap\"\u003e table.\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eOn termination the SAFT application removes the 'follow up' script and copies the SAFT log into the \u003ccode\u003e/var/fw_test_log.txt\u003c/code\u003e, which allows the operator to examine the test results.\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Running-SAFT\" /\u003eRunning SAFT\u003c/h3\u003e\r\n\u003cdiv\u003eTwo important conditions have to be met before SAFT can run properly:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eboth kernels/root fs pairs need to be populated on the main storage device\u003c/li\u003e\r\n\u003cli\u003ethe flash device needs to be configured not to use verified root fs, because it gets mounted in course of SAFT execution, which causes verified root fs control structures to go out of sync. \u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eNeither of these conditions are met by default in the recent ChromeOS distributions, so before SAFT can run, they need to be taken care of. The SAFT wrapper script\u003ccode\u003e /usr/sbin/firmware/saft/runtests.sh\u003c/code\u003e does that. The wrapper script checks if both partiton pairs exist, and if not - it duplicates the firs pair on the second pair's devices (\u003ccode\u003e/dev/sda2\u003c/code\u003e gets copied to \u003ccode\u003e/dev/sda4\u003c/code\u003e and \u003ccode\u003e/dev/sda3\u003c/code\u003e gets copied to \u003ccode\u003e/dev/sda5\u003c/code\u003e) and checks the command line of the flash device hosted recovery kernel. If it is configured to run with verified root fs, the kernel command line is edited to bring the recovery image up without verified root fs protection.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eSo, a typical procedure to invoke SAFT is as follows:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003edownload ChromeOS test distribution and put it on the flash drive\u003c/li\u003e\r\n\u003cli\u003einstall ChromeOS on the target using the flash drive\u003c/li\u003e\r\n\u003cli\u003ereboot the target, enter the shell dialog and type\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\r\n\u003cdiv\u003e\u003ccode\u003esudo /usr/sbin/firmware/saft/runtests.sh [\u0026lt;BIOS image to test\u0026gt;]\u003c/code\u003e\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\nIf \u003ccode\u003eruntests.sh\u003c/code\u003e is invoked without any parameters, it just verifies the environment (modifies it as described above, if required), copies SAFT code into the removable device (into\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e \u0026lt;flash drive mount point\u0026gt;\u003c/code\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003e/usr/sbin/firmware/saft)\u003c/code\u003e and runs SAFT unit tests. The actual SAFT starts if \u003ccode\u003eruntests.sh\u003c/code\u003e is invoked with a command line parameter, the name of the file containing the firmware image to test.\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIt is presumed that the flash device (carrying the recovery image from which the system has been installed) is plugged in into the target and gets instantiated as \u003ccode\u003e/dev/sdb\u003c/code\u003e. If the flash device is plugged in into a USB hub or is instantiated as a different device for some other reason, the environment variable \u003ccode\u003eFLASH_DEVICE \u003c/code\u003ecan be used to communicate it to the script, for instance:\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eFLASH_DEVICE\u003dsdc /usr/sbin/firmware/saft/runtests.sh [\u0026lt;BIOS image to test\u0026gt;]\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eWhen invoked with the BIOS image file name, it is verified that the image has proper keys in it and would be able to bring up the existing kernels. If verification succeeds, SAFT gets under way, rebooting the target a few times (as many times as there are steps in \u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003esaft_utility.py:\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:monospace;font-size:medium;white-space:pre-wrap\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003eTEST_STATE_SEQUENCE\u003c/code\u003e\u003ccode\u003e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003cspan style\u003d\"white-space:normal\"\u003e)\u003c/span\u003e\u003c/font\u003e\u003c/code\u003e\u003ccode\u003e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003cspan style\u003d\"white-space:normal\"\u003e.\u003c/span\u003e\u003c/font\u003e\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eCertain steps take a long time between restarts (for instance, when a step involves reprogramming of the flashrom). It is easy to tell if SAFT is completed or not by examining the SAFT temp file in \u003ccode\u003e/tmp/saft.log\u003c/code\u003e. When SAFT completes, this file would have either an error message or the phrase 'we are done' in the end. This file includes only messages generated since the most recent startup. The full SAFT log can be found in \u003ccode\u003e/var/fw_test.log.txt\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e \u003cb\u003eafter \u003c/b\u003ethe test completes.\u003c/font\u003e\u003c/code\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Tests-implemented-so-far\" /\u003e\u003ccode\u003e\u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003eTests implemented so\u003c/font\u003e\u003c/code\u003e far\u003c/h3\u003e\r\n\u003cdiv\u003eThe following tests are implemented as of commit \u003ccode\u003e6cabd80 Introduce gpt tests in SAFT\u003c/code\u003e. (make sure to update this string when editing this section).\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ctable border\u003d\"1\" bordercolor\u003d\"#888\" cellspacing\u003d\"0\" style\u003d\"border-collapse:collapse;border-top-color:rgb(136,136,136);border-right-color:rgb(136,136,136);border-bottom-color:rgb(136,136,136);border-left-color:rgb(136,136,136);border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px\"\u003e\r\n\u003ctbody\u003e\r\n\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:23px\"\u003e Test\u003c/td\u003e\r\n\u003ctd colspan\u003d\"3\" style\u003d\"text-align:center;width:324px;height:23px\"\u003e      System state after reboot\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e \u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e Firmware\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e Kernel\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:202px;height:15px\"\u003e GPT attributes\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Set 'try FW B' in NV ram\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e  B\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e A \u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Corrupt FW A\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e B\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e A\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Restore FW A\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e  A\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e A\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Corrupt both FW A and B\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e Recovery\u003c/td\u003e\r\n\u003ctd style\u003d\"width:52px;height:15px\"\u003e\u003cspan style\u003d\"border-collapse:separate\"\u003eRecovery\u003c/span\u003e\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Restore FW A and B\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003eA\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e A\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Corrupt kernel A\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e  A\u003cspan\u003e \u003c/span\u003e\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e B\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Corrupt kernel B\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e Recovery\u003c/td\u003e\r\n\u003ctd style\u003d\"width:52px;height:15px\"\u003eRecovery\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Restore kernels A and B\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e A\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e A\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"width:202px;height:15px\"\u003e \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"width:270px;height:15px\"\u003e Set GPT A[S:0 T:15 P:10] B[S:0 T\u003d15 P\u003d9]\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:70px;height:15px\"\u003e A\u003c/td\u003e\r\n\u003ctd style\u003d\"text-align:center;width:52px;height:15px\"\u003e A\u003c/td\u003e\r\n\r\n\u003ctd style\u003d\"text-align:center;width:202px;height:15px\"\u003eA[S:0 T:14 P:10] B[S:0 T\u003d15 P\u003d9] \u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\u003c/table\u003e\r\n\u003cdiv\u003e\u003cspan style\u003d\"font-size:16px;font-weight:bold\"\u003e\u003cbr /\u003e\r\n\u003c/span\u003e\u003c/div\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Enhancing-SAFT\" /\u003eEnhancing SAFT\u003c/h3\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eIt is easy to add new steps to SAFT by extending \u003cfont color\u003d\"#000000\" face\u003d\"Arial, Verdana, sans-serif\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003esaft_utility.py:\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"font-family:monospace;font-size:medium;white-space:pre-wrap\"\u003e\u003ccode style\u003d\"color:rgb(0,96,0)\"\u003eTEST_STATE_SEQUENCE\u003c/code\u003e\u003c/span\u003e table with new steps. The format of the table is simple, each line is a tri-tuple of\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e(\u0026lt;boot_state_vector\u0026gt;, \u0026lt;function\u0026gt;, \u0026lt;argument\u0026gt;),\u003c/code\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003ewhere \u003ccode\u003eboot_state_vector\u003c/code\u003e is the expected boot state after the previous step, and \u003ccode\u003efunction\u003c/code\u003e with argument \u003ccode\u003eargument\u003c/code\u003e will implement the new step of SAFT.\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Interpreting-SAFT-errors\" /\u003eInterpreting SAFT errors\u003c/h3\u003e\u003cdiv\u003eOne of the common SAFT errors is 'wrong boot vector'\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3087306851372487833"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/for-testers/saft"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4135472737682618275"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4135472737682618275"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4135472737682618275"}],"author":[{"name":{"$t":"Vadim Bendebury"},"email":{"$t":"vbendeb@chromium.org"}}],"sites$pageName":{"$t":"saft"},"sites$revision":{"$t":"20"}},{"gd$etag":"\"YDUpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1706892219954116291"},"published":{"$t":"2014-02-23T19:44:24.246Z"},"updated":{"$t":"2014-02-23T22:37:44.065Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-23T22:37:42.838Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Upstream coreboot on Intel Haswell Chromebook"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv /\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Disable-write-protection-by-following-the-Chromium-OS-wiki-\" /\u003e\u003cfont size\u003d\"3\"\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eDisable write protection by following the \u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices\" style\u003d\"background-color:transparent\"\u003eChromium OS wiki\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e \u003c/span\u003e\u003c/font\u003e\u003c/h3\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eOpen device\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eRemove write protect screw\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eBoot device in developer mode\u003c/span\u003e\u003c/li\u003e\u003cli\u003eDisable flash write protection\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eflashrom --wp-disable\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Check-out-coreboot\" /\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eCheck out coreboot\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003egit clone http://review.coreboot.org/p/coreboot\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003ecd coreboot\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Extract-BIOS-from-running-system\" /\u003eExtract BIOS from running system\u003c/h3\u003e\u003cdiv\u003eThe BIOS from the running system will contain some specific data in GBB and VPD regions that are unique.  It is recommended to extract and save this BIOS in case you want to restore to previous unique device information.  Without a valid HWID the system will be unable to recover or receive updates.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003eflashrom -r device_bios.bin\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Extract-BIOS-from-Firmware-Update-utility-on-the-device\" /\u003eExtract BIOS from Firmware Update utility on the device\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eThe BIOS extracted from a running system does not contain the Management Engine firmware as that region is not readable from the host.  The firmware update utility contains a raw BIOS update image which will contain the Management Engine binary.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eCopy /usr/sbin/chromeos-firwmwareupdate from device, execute, and copy bios.bin to coreboot root.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003echromeos-firwmareupdate --sb_extract /tmp\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003ecp /tmp/bios.bin .\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Extract-SPI-Descriptor-and-Management-Engine-binary\" /\u003eExtract SPI Descriptor and Management Engine binary\u003c/h3\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eifdtool -x bios.bin\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Extract-MRC-binary\" /\u003eExtract MRC binary\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003ecbfstool bios.bin extract -n mrc.bin -f mrc.bin\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Extract-VBIOS-binary\" /\u003eExtract VBIOS binary\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Save-as-PCI-Device-ID-0x0a06-to-make-SeaBIOS-happy\" /\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt;font-weight:normal\"\u003eSave as PCI Device ID 0x0a06 to make SeaBIOS happy\u003c/span\u003e\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003ecbfstool bios.bin extract -n pci8086,0406.rom -f pci8086,0a06.rom\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Configure-Coreboot\" /\u003eConfigure Coreboot\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003emake menuconfig\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Suggested-Settings\" /\u003eSuggested Settings\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e\u0026gt; Mainboard -\u0026gt; Mainboard Vendor -\u0026gt; Google\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; Mainboard -\u0026gt; Mainboard Model -\u0026gt; Falco\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; Chipset -\u0026gt; Add a System Agent binary -\u0026gt; mrc.bin\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; VGA BIOS -\u0026gt; Add a VGA BIOS image -\u0026gt; pci8086,0a06.rom\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; VGA BIOS -\u0026gt; VGA device PCI IDs -\u0026gt; 8086,0a06\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; Console -\u0026gt; Serial port console output -\u0026gt; DISABLE\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; Payload -\u0026gt; Add a payload -\u0026gt; SeaBIOS\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; Payload -\u0026gt; SeaBIOS version -\u0026gt; master\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u0026gt; ChromeOS -\u0026gt; Build for ChromeOS -\u0026gt; DISABLE\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Build-Coreboot-and-SeaBIOS\" /\u003e\u003cspan style\u003d\"background-color:transparent;font-size:medium\"\u003eBuild Coreboot and SeaBIOS\u003c/span\u003e\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003emake\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Configure-SeaBIOS-to-use-ESC-key-instead-of-F12\" /\u003eConfigure SeaBIOS to use ESC key instead of F12\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eecho -ne \"\\x01\" \u0026gt; boot-menu-key\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eecho -e \"\\nPress ESC for boot menu.\\n\" \u0026gt; boot-menu-message\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003ecbfstool build/coreboot.rom add -f boot-menu-key -n etc/boot-menu-key -t raw\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003ecbfstool build/coreboot.rom add -f boot-menu-message -n etc/boot-menu-message -t raw\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIf setting a boot splash screen:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003ecbfstool build/coreboot.rom add -f bootsplash.jpg -n bootsplash.jpg -t raw\u003c/code\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Add-SPI-Descriptor\" /\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eAdd SPI Descriptor\u003c/font\u003e\u003c/span\u003e\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003edd if\u003dflashregion_0_flashdescriptor.bin of\u003dbuild/coreboot.rom conv\u003dnotrunc\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Add-Management-Engine\" /\u003eAdd Management Engine\u003c/h3\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eifdtool -i me:flashregion_2_intel_me.bin build/coreboot.rom\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003emv build/coreboot.rom.new build/coreboot.rom\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2461203149256614225"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/upstream-coreboot-on-intel-haswell-chromebook"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1706892219954116291"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1706892219954116291"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1706892219954116291"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$pageName":{"$t":"upstream-coreboot-on-intel-haswell-chromebook"},"sites$revision":{"$t":"9"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/969150080970293470"},"published":{"$t":"2014-02-23T19:37:16.959Z"},"updated":{"$t":"2014-02-23T19:37:16.986Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-23T19:37:16.959Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"chromebook_leon_write_protect.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/969150080970293470"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5581542598653454687"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/toshiba-cb30-chromebook/chromebook_leon_write_protect.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/969150080970293470"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/969150080970293470"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/969150080970293470"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/969150080970293470"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6936776287954001624"},"published":{"$t":"2014-02-23T19:31:19.658Z"},"updated":{"$t":"2014-02-23T19:31:19.757Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-23T19:31:19.658Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"c720-chromebook-innards.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6936776287954001624"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5581542598653454687"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/toshiba-cb30-chromebook/c720-chromebook-innards.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6936776287954001624"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6936776287954001624"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6936776287954001624"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6936776287954001624"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3967352112453848951"},"published":{"$t":"2014-02-21T21:11:50.762Z"},"updated":{"$t":"2014-02-21T21:11:50.813Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-21T21:11:50.762Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"2014 Chrome OS Firmware Summit- Overview.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3967352112453848951"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/2014%20Chrome%20OS%20Firmware%20Summit-%20Overview.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3967352112453848951"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3967352112453848951"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3967352112453848951"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3967352112453848951"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6068276961774238574"},"published":{"$t":"2014-02-21T21:11:47.618Z"},"updated":{"$t":"2014-02-21T21:11:47.652Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-21T21:11:47.618Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"x86 coreboot porting.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/6068276961774238574"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/x86%20coreboot%20porting.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6068276961774238574"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6068276961774238574"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6068276961774238574"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/6068276961774238574"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2992083967988199514"},"published":{"$t":"2014-02-21T21:11:45.259Z"},"updated":{"$t":"2014-02-21T21:11:45.295Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-21T21:11:45.259Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"ARM coreboot porting.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2992083967988199514"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/ARM%20coreboot%20porting.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2992083967988199514"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2992083967988199514"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2992083967988199514"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2992083967988199514"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8744425954761079010"},"published":{"$t":"2014-02-21T21:11:42.997Z"},"updated":{"$t":"2014-02-21T21:11:43.031Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-21T21:11:42.997Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Coreboot Mainboard Porting.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8744425954761079010"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/Coreboot%20Mainboard%20Porting.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8744425954761079010"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8744425954761079010"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8744425954761079010"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8744425954761079010"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/590951457030606050"},"published":{"$t":"2014-02-21T21:11:40.659Z"},"updated":{"$t":"2014-02-21T21:11:40.690Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-21T21:11:40.659Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"ChromeOS firmware summit - Depthcharge.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/590951457030606050"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/ChromeOS%20firmware%20summit%20-%20Depthcharge.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/590951457030606050"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/590951457030606050"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/590951457030606050"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/590951457030606050"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3089912642339271449"},"published":{"$t":"2014-02-21T21:11:32.144Z"},"updated":{"$t":"2014-02-21T21:11:32.180Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-21T21:11:32.144Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Chrome OS Firmware Summit- Sundries.pdf"},"summary":{},"content":{"type":"application/pdf","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3089912642339271449"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6459465170770489524"},{"rel":"alternate","type":"application/pdf","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/2014-firmware-summit/Chrome%20OS%20Firmware%20Summit-%20Sundries.pdf"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3089912642339271449"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3089912642339271449"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3089912642339271449"},{"rel":"edit-media","type":"application/pdf","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3089912642339271449"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3185366824488474522"},"published":{"$t":"2008-08-26T00:20:05.420Z"},"updated":{"$t":"2014-02-21T00:48:49.592Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2011-09-21T14:53:30.903Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Browser Window"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eThe Chromium browser window is represented by several objects, some of which are included in this diagram:\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/browser-window/BrowserWindow2.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1235884937125/developers/design-documents/browser-window/BrowserWindow2.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Frame\" /\u003eFrame\u003c/h2\u003e\u003cdiv\u003eThe frame is the portion of the browser window that includes the title bar, sizing borders, and other areas traditionally known as the \"non-client\" areas in Windows terminology. We supply a frame (called \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eBrowserFrame\u003c/span\u003e) that subclasses the \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eviews::Widget\u003c/span\u003e class that adds some additional handling on Vista for DWM adjustments behind the TabStrip, etc.\u003cbr /\u003e\u003cbr /\u003eOn Windows Vista, we only use the glass mode when desktop compositing is enabled; in Classic or Vista Basic modes we use the XP Luna mode. Because the user is able to toggle the compositing on and off by changing Windows themes, we need to be able to dynamically change frame mode. For more information about how this is done in views, see the \u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003ca href\u003d\"goog_1235887298838\"\u003eviews::Widget\u003c/a\u003e\u003c/span\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/views-windowing\"\u003e documentation\u003c/a\u003e. The browser window provides two \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eNonClientFrameView\u003c/span\u003e subclasses - \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eGlassBrowserFrameView\u003c/span\u003e and \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eOpaqueBrowserFrameView\u003c/span\u003e which are swapped in the \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eBrowserFrame\u003c/span\u003e's \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eNonClientView\u003c/span\u003e when DWM is toggled.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:22px;font-weight:bold\"\u003eBrowser View\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003eThe \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eBrowserView\u003c/span\u003e object contains all of the elements that are common between the frames that are part of the presentation of the browser window - the tab strip, the toolbar, the bookmarks bar, and other elements of the UI. When the frame changes, this View is inserted into the new \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eNonClientView\u003c/span\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eBrowserView\u003c/span\u003e implements an interface called \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eBrowserWindow\u003c/span\u003e, which the \u003cspan style\u003d\"font-family:courier new,monospace\"\u003eBrowser\u003c/span\u003e object uses to interact with the View.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Browser\" /\u003eBrowser\u003c/h2\u003e\u003cdiv\u003eThis is the core state and command execution component of a Browser window. It interacts with an abstract Browser Window interface to update the UI. This allows us to write unit tests that supply a windowless \"testing view\" and then execute high-level functionality within the browser from within the unit testing framework, rather than running UI tests.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/browser-window"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3185366824488474522"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3185366824488474522"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3185366824488474522"}],"author":[{"name":{"$t":"Mike Jeffrey"},"email":{"$t":"mjeffrey@google.com"}}],"sites$pageName":{"$t":"browser-window"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2582646673705051924"},"published":{"$t":"2013-09-24T12:04:28.803Z"},"updated":{"$t":"2014-02-20T12:29:16.997Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-20T12:29:15.588Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"DOM Exceptions"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cb style\u003d\"font-size:10pt\"\u003eUseful error messages with \u003cfont face\u003d\"courier new, monospace\"\u003eExceptionMessages\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003eWhen throwing a DOM exception, please ensure that you take the time to write an error message that helps developers understand what's gone wrong, and what they can do to fix things. Something like \u003cfont face\u003d\"courier new, monospace\"\u003eexceptionState.throwDOMException(InvalidStateError, \"This object's 'readyState' is not 'open'.\")\u003c/font\u003e can make the difference between a 5 minute fix, and an all-day facepalming session. The \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ca href\u003d\"http://cs.chromium.org/ExceptionMessages.h\"\u003eExceptionMessages\u003c/a\u003e\u003c/font\u003e helper class has a variety of methods that help you construct a more detailed and specific message in a consistent way. Perhaps:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"courier new, monospace\" style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont style\u003d\"font-size:10pt\"\u003e    \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\" style\u003d\"font-size:10pt\"\u003ees.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, \"Node\"));\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThat will give the user an exception object whose message property reads \"\u003cfont face\u003d\"courier new, monospace\"\u003eFailed to execute \"method\" on \"Interface\": The 1st argument is null, or an invalid Node object.\u003c/font\u003e\", which has been scientifically measured to be 83 times more useful than an exception lacking that detail. In general, d\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eevelopers will be much happier if we give them enough data to resolve an issue right away, so please don't be afraid of adding detail.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eJust add\u003cfont face\u003d\"courier new, monospace\"\u003e #include \"bindings/v8/ExceptionMessages.h\"\u003c/font\u003e and go wild.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eSecurity considerations\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eException messages are exposed to the web via JavaScript. Please be very careful when throwing exceptions that might expose interesting data cross-origin. In particular, \u003cfont face\u003d\"courier new, monospace\"\u003eSecurityError\u003c/font\u003e messages are prone to this sort of accidental leakage.\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eAlways throw \u003cfont face\u003d\"courier new, monospace\"\u003eSecurityError\u003c/font\u003e exceptions via \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ca href\u003d\"http://cs.chromium.org/ExceptionState::throwSecurityError\"\u003eExceptionState::throwSecurityError\u003c/a\u003e\u003c/font\u003e.\u003c/li\u003e\u003cli\u003eEnsure that the \u003cfont face\u003d\"courier new, monospace\"\u003esanitizedMessage\u003c/font\u003e (first parameter) can safely be exposed to JavaScript.\u003c/li\u003e\u003cli\u003eAdd additional detail via an \u003cfont face\u003d\"courier new, monospace\"\u003eunsanitizedMessage\u003c/font\u003e (second parameter) if relevant.\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003ePractical examples of this include \u003cfont face\u003d\"courier new, monospace\"\u003eDOMWindow::sanitizedCrossDomainAccessErrorMessage\u003c/font\u003e and \u003cfont face\u003d\"courier new, monospace\"\u003eDOMWindow::crossDomainAccessErrorMessage\u003c/font\u003e\u003cfont face\u003d\"arial, sans-serif\"\u003e. We call both of these methods from inside \u003c/font\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003ca href\u003d\"http://cs.chromium.org/V8Initializer%20failedAccessCheckCallbackInMainThread\"\u003eV8Initializer::failedAccessCheckCallbackInMainThread\u003c/a\u003e\u003c/font\u003e to ensure that JavaScript can't access details about cross-origin frames, but that those details appear in the console if the exceptions aren't caught.\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2023764670965291136"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/blink/dom-exceptions"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2582646673705051924"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2582646673705051924"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2582646673705051924"}],"author":[{"name":{"$t":"Mike West"},"email":{"$t":"mkwst@chromium.org"}}],"sites$pageName":{"$t":"dom-exceptions"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7528044324141715169"},"published":{"$t":"2014-02-19T23:32:21.422Z"},"updated":{"$t":"2014-02-19T23:51:24.509Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-19T23:51:23.631Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Firmware Summit 2014"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cfont size\u003d\"4\"\u003eAgenda and Slides\u003c/font\u003e\u003c/div\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003eChromium OS Firmware Overview\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003ecoreboot Overview and Features\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003ecoreboot Porting to x86\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003ecoreboot Porting to ARM\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003ecoreboot Porting to Mainboard\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003eDepthcharge\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003eEmbedded Controller\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"4\"\u003eChromium Process\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/593897542665142458"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/firmware-summit"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7528044324141715169"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7528044324141715169"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7528044324141715169"}],"author":[{"name":{"$t":"Duncan Laurie"},"email":{"$t":"dlaurie@chromium.org"}}],"sites$pageName":{"$t":"firmware-summit"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5825100101924839608"},"published":{"$t":"2014-02-05T22:31:13.582Z"},"updated":{"$t":"2014-02-11T01:41:24.870Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-10T23:55:55.950Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"SPDY Protocol - Draft 3.2"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003e1. Overview\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.1-Document-Organization\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003e1.1 Document Organization\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.2-Definitions\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003e1.2 Definitions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.-SPDY-Framing-Layer\"\u003e\u003cstrong\u003e2 \u003c/strong\u003e2. SPDY Framing Layer\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.1-Session-Connections-\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003e2.1 Session (Connections)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2-Framing\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003e2.2 Framing\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2.1-Control-frames\"\u003e\u003cstrong\u003e2.2.1 \u003c/strong\u003e2.2.1 Control frames\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2.2-Data-frames\"\u003e\u003cstrong\u003e2.2.2 \u003c/strong\u003e2.2.2 Data frames\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3-Streams\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003e2.3 Streams\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.1-Stream-frames\"\u003e\u003cstrong\u003e2.3.1 \u003c/strong\u003e2.3.1 Stream frames\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2-Stream-creation\"\u003e\u003cstrong\u003e2.3.2 \u003c/strong\u003e2.3.2 Stream creation\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2.1-Unidirectional-streams\"\u003e\u003cstrong\u003e2.3.2.1 \u003c/strong\u003e2.3.2.1 Unidirectional streams\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2.2-Bidirectional-streams\"\u003e\u003cstrong\u003e2.3.2.2 \u003c/strong\u003e2.3.2.2 Bidirectional streams\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.3-Stream-priority\"\u003e\u003cstrong\u003e2.3.3 \u003c/strong\u003e2.3.3 Stream priority\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.4-Stream-headers\"\u003e\u003cstrong\u003e2.3.4 \u003c/strong\u003e2.3.4 Stream headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.5-Stream-data-exchange\"\u003e\u003cstrong\u003e2.3.5 \u003c/strong\u003e2.3.5 Stream data exchange\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.6-Stream-half-close\"\u003e\u003cstrong\u003e2.3.6 \u003c/strong\u003e2.3.6 Stream half-close\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.7-Stream-close\"\u003e\u003cstrong\u003e2.3.7 \u003c/strong\u003e2.3.7 Stream close\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4-Error-Handling\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003e2.4 Error Handling\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4.1-Session-Error-Handling\"\u003e\u003cstrong\u003e2.4.1 \u003c/strong\u003e2.4.1 Session Error Handling\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4.2-Stream-Error-Handling\"\u003e\u003cstrong\u003e2.4.2 \u003c/strong\u003e2.4.2 Stream Error Handling\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.5-Data-flow\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003e2.5 Data flow\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6-Control-frame-types\"\u003e\u003cstrong\u003e2.6 \u003c/strong\u003e2.6 Control frame types\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.1-SYN_STREAM\"\u003e\u003cstrong\u003e2.6.1 \u003c/strong\u003e2.6.1 SYN_STREAM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.2-SYN_REPLY\"\u003e\u003cstrong\u003e2.6.2 \u003c/strong\u003e2.6.2 SYN_REPLY\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.3-RST_STREAM\"\u003e\u003cstrong\u003e2.6.3 \u003c/strong\u003e2.6.3 RST_STREAM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.4-SETTINGS\"\u003e\u003cstrong\u003e2.6.4 \u003c/strong\u003e2.6.4 SETTINGS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.5-PING\"\u003e\u003cstrong\u003e2.6.5 \u003c/strong\u003e2.6.5 PING\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.6-GOAWAY\"\u003e\u003cstrong\u003e2.6.6 \u003c/strong\u003e2.6.6 GOAWAY\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.7-HEADERS\"\u003e\u003cstrong\u003e2.6.7 \u003c/strong\u003e2.6.7 HEADERS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.8-WINDOW_UPDATE\"\u003e\u003cstrong\u003e2.6.8 \u003c/strong\u003e2.6.8 WINDOW_UPDATE\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-The-Flow-Control-Window\"\u003e\u003cstrong\u003e2.6.8.1 \u003c/strong\u003eThe Flow Control Window\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Initial-Flow-Control-Window-Size\"\u003e\u003cstrong\u003e2.6.8.2 \u003c/strong\u003eInitial Flow Control Window Size\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Reducing-the-Stream-Window-Size\"\u003e\u003cstrong\u003e2.6.8.3 \u003c/strong\u003eReducing the Stream Window Size\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.9-CREDENTIAL\"\u003e\u003cstrong\u003e2.6.9 \u003c/strong\u003e2.6.9 CREDENTIAL\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.10-Name-Value-Header-Block\"\u003e\u003cstrong\u003e2.6.10 \u003c/strong\u003e2.6.10 Name/Value Header Block\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.10.1-Compression\"\u003e\u003cstrong\u003e2.6.10.1 \u003c/strong\u003e2.6.10.1 Compression\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.-HTTP-Layering-over-SPDY\"\u003e\u003cstrong\u003e3 \u003c/strong\u003e3. HTTP Layering over SPDY\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.1-Connection-Management\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003e3.1 Connection Management\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.1.1-Use-of-GOAWAY\"\u003e\u003cstrong\u003e3.1.1 \u003c/strong\u003e3.1.1 Use of GOAWAY\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2-HTTP-Request-Response\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003e3.2 HTTP Request/Response\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.1-Request\"\u003e\u003cstrong\u003e3.2.1 \u003c/strong\u003e3.2.1 Request\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.2-Response\"\u003e\u003cstrong\u003e3.2.2 \u003c/strong\u003e3.2.2 Response\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3-Authentication\"\u003e\u003cstrong\u003e3.2.3 \u003c/strong\u003e3.2.3 Authentication\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3.1-Stateless-Authentication\"\u003e\u003cstrong\u003e3.2.3.1 \u003c/strong\u003e3.2.3.1 Stateless Authentication\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3.2-Stateful-Authentication\"\u003e\u003cstrong\u003e3.2.3.2 \u003c/strong\u003e3.2.3.2 Stateful Authentication\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3-Server-Push-Transactions\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003e3.3 Server Push Transactions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3.1-Server-implementation\"\u003e\u003cstrong\u003e3.3.1 \u003c/strong\u003e3.3.1 Server implementation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3.2-Client-implementation\"\u003e\u003cstrong\u003e3.3.2 \u003c/strong\u003e3.3.2 Client implementation\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.-Design-Rationale-and-Notes\"\u003e\u003cstrong\u003e4 \u003c/strong\u003e4. Design Rationale and Notes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.1-Separation-of-Framing-Layer-and-Application-Layer\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003e4.1 Separation of Framing Layer and Application Layer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.2-Error-handling---Framing-Layer\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003e4.2 Error handling - Framing Layer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.3-One-Connection-Per-Domain\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003e4.3 One Connection Per Domain\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.4-Fixed-vs-Variable-Length-Fields\"\u003e\u003cstrong\u003e4.4 \u003c/strong\u003e4.4 Fixed vs Variable Length Fields\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.5-Compression-Context-s-\"\u003e\u003cstrong\u003e4.5 \u003c/strong\u003e4.5 Compression Context(s)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.6-Unidirectional-streams\"\u003e\u003cstrong\u003e4.6 \u003c/strong\u003e4.6 Unidirectional streams\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.7-Data-Compression\"\u003e\u003cstrong\u003e4.7 \u003c/strong\u003e4.7 Data Compression\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.8-Server-Push\"\u003e\u003cstrong\u003e4.8 \u003c/strong\u003e4.8 Server Push\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.-Security-Considerations\"\u003e\u003cstrong\u003e5 \u003c/strong\u003e5. Security Considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.1-Use-of-Same-origin-constraints\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003e5.1 Use of Same-origin constraints\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.2-HTTP-Headers-and-SPDY-Headers\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003e5.2 HTTP Headers and SPDY Headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.3-Cross-Protocol-Attacks\"\u003e\u003cstrong\u003e5.3 \u003c/strong\u003e5.3 Cross-Protocol Attacks\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.4-Server-Push-Implicit-Headers\"\u003e\u003cstrong\u003e5.4 \u003c/strong\u003e5.4 Server Push Implicit Headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.5-Use-of-Padding\"\u003e\u003cstrong\u003e5.5 \u003c/strong\u003e5.5 Use of Padding\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.-Privacy-Considerations\"\u003e\u003cstrong\u003e6 \u003c/strong\u003e6. Privacy Considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.1-Long-Lived-Connections\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003e6.1 Long Lived Connections\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.2-SETTINGS-frame\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003e6.2 SETTINGS frame\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-7.-Incompatibilities-with-SPDY-draft-3\"\u003e\u003cstrong\u003e7 \u003c/strong\u003e7. Incompatibilities with SPDY draft 3\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-8.-Requirements-Notation\"\u003e\u003cstrong\u003e8 \u003c/strong\u003e8. Requirements Notation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-9.-Acknowledgements\"\u003e\u003cstrong\u003e9 \u003c/strong\u003e9. Acknowledgements\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-10.-Normative-References\"\u003e\u003cstrong\u003e10 \u003c/strong\u003e10. Normative References\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-11.-Errata\"\u003e\u003cstrong\u003e11 \u003c/strong\u003e11. Errata\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Authors-Addresses\"\u003e\u003cstrong\u003e12 \u003c/strong\u003eAuthors' Addresses\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-1.-Overview\" /\u003e1. Overview\u003c/h1\u003e\u003cp\u003eOne of the bottlenecks of HTTP implementations is that HTTP relies on multiple connections for concurrency. This causes several problems, including additional round trips for connection setup, slow-start delays, and connection rationing by the client, where it tries to avoid opening too many connections to any single server. HTTP pipelining helps some, but only achieves partial multiplexing. In addition, pipelining has proven non-deployable in existing browsers due to intermediary interference.\u003c/p\u003e\u003cp\u003eSPDY adds a framing layer for multiplexing multiple, concurrent streams across a single TCP connection (or any reliable transport stream). The framing layer is optimized for HTTP-like request-response streams, such that applications which run over HTTP today can work over SPDY with little or no change on behalf of the web application writer.\u003c/p\u003e\u003cp\u003eThe SPDY session offers four improvements over HTTP:\u003c/p\u003e\u003cul\u003e\u003cli\u003eMultiplexed requests: There is no limit to the number of requests that can be issued concurrently over a single SPDY connection.\u003c/li\u003e\u003cli\u003ePrioritized requests: Clients can request certain resources to be delivered first. This avoids the problem of congesting the network channel with non-critical resources when a high-priority request is pending.\u003c/li\u003e\u003cli\u003eCompressed headers: Clients today send a significant amount of redundant data in the form of HTTP headers. Because a single web page may require 50 or 100 subrequests, this data is significant.\u003c/li\u003e\u003cli\u003eServer pushed streams: Server Push enables content to be pushed from servers to clients without a request.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eSPDY attempts to preserve the existing semantics of HTTP. All features such as cookies, ETags, Vary headers, Content-Encoding negotiations, etc work as they do with HTTP; SPDY only replaces the way the data is written to the network.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1.1-Document-Organization\" /\u003e1.1 Document Organization\u003c/h2\u003e\u003cp\u003eThe SPDY Specification is split into two parts: a framing layer (Section 2), which multiplexes a TCP connection into independent, length-prefixed frames, and an HTTP layer (Section 3), which specifies the mechanism for overlaying HTTP request/response pairs on top of the framing layer. While some of the framing layer concepts are isolated from the HTTP layer, building a generic framing layer has not been a goal. The framing layer is tailored to the needs of the HTTP protocol and server push.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1.2-Definitions\" /\u003e1.2 Definitions\u003c/h2\u003e\u003cul\u003e\u003cli\u003eclient: The endpoint initiating the SPDY session.\u003c/li\u003e\u003cli\u003econnection: A transport-level connection between two endpoints.\u003c/li\u003e\u003cli\u003eendpoint: Either the client or server of a connection.\u003c/li\u003e\u003cli\u003eframe: A header-prefixed sequence of bytes sent over a SPDY session.\u003c/li\u003e\u003cli\u003eserver: The endpoint which did not initiate the SPDY session.\u003c/li\u003e\u003cli\u003esession: A synonym for a connection.\u003c/li\u003e\u003cli\u003esession error: An error on the SPDY session.\u003c/li\u003e\u003cli\u003estream: A bi-directional flow of bytes across a virtual channel within a SPDY session.\u003c/li\u003e\u003cli\u003estream error: An error on an individual SPDY stream.\u003c/li\u003e\u003c/ul\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-2.-SPDY-Framing-Layer\" /\u003e2. SPDY Framing Layer\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.1-Session-Connections-\" /\u003e2.1 Session (Connections)\u003c/h2\u003e\u003cp\u003eThe SPDY framing layer (or \"session\") runs atop a reliable transport layer such as TCP. The client is the TCP connection initiator. SPDY connections are persistent connections.\u003c/p\u003e\u003cp\u003eFor best performance, it is expected that clients will not close open connections until the user navigates away from all web pages referencing a connection, or until the server closes the connection. Servers are encouraged to leave connections open for as long as possible, but can terminate idle connections if necessary. When either endpoint closes the transport-level connection, it MUST first send a GOAWAY (Section 2.6.6) frame so that the endpoints can reliably determine if requests finished before the close.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.2-Framing\" /\u003e2.2 Framing\u003c/h2\u003e\u003cp\u003eOnce the connection is established, clients and servers exchange framed messages. There are two types of frames: control frames (Section 2.2.1) and data frames (Section 2.2.2). Frames always have a common header which is 8 bytes in length.\u003c/p\u003e\u003cp\u003eThe first bit is a control bit indicating whether a frame is a control frame or data frame. Control frames carry a version number, a frame type, flags, and a length. Data frames contain the stream ID, flags, and the length for the payload carried after the common header. The simple header is designed to make reading and writing of frames easy.\u003c/p\u003e\u003cp\u003eAll integer values, including length, version, and type, are in network byte order. SPDY does not enforce alignment of types in dynamically sized frames.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.2.1-Control-frames\" /\u003e2.2.1 Control frames\u003c/h3\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|C| Version(15bits) | Type(16bits) |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Data |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The 'C' bit is a single bit indicating if this is a control message. For control frames this value is always 1.\u003c/p\u003e\u003cp\u003eVersion: The version number of the SPDY protocol. This document describes SPDY version 3.1, which is represented as version 3.\u003c/p\u003e\u003cp\u003eType: The type of control frame. See Control Frames (Section 2.6) for the complete list of control frames.\u003c/p\u003e\u003cp\u003eFlags: Flags related to this frame. Flags for control frames and data frames are different.\u003c/p\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field.\u003c/p\u003e\u003cp\u003eData: data associated with this control frame. The format and length of this data is controlled by the control frame type.\u003c/p\u003e\u003cp\u003eControl frame processing requirements:\u003c/p\u003e\u003cul\u003e\u003cli\u003eNote that full length control frames (16MB) can be large for implementations running on resource-limited hardware. In such cases, implementations MAY limit the maximum length frame supported. However, all implementations MUST be able to receive control frames of at least 8192 octets in length.\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.2.2-Data-frames\" /\u003e2.2.2 Data frames\u003c/h3\u003e\u003cdiv /\u003e\u003cpre\u003e+-------------------------------------+\r\n|C| Stream-ID (31bits) |\r\n+-------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+-------------------------------------+\r\n|[Pad High (8)]|[Pad Low (8)]|Data (*)|\r\n+-------------------------------------+\r\n| Data (*) |\r\n+-------------------------------------+\r\n| Padding (*) |\r\n+-------------------------------------+\u003c/pre\u003e\u003cpre\u003e \u003c/pre\u003e\u003cp\u003eControl bit: For data frames this value is always 0.\u003c/p\u003e\u003cp\u003eStream-ID: A 31-bit value identifying the stream.\u003c/p\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - signifies that this frame represents the last frame to be transmitted on this stream. See Stream Close (Section 2.3.7) below.\u003c/li\u003e\u003cli\u003e0x04 \u003d PAD_LOW - b\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eit 3 being set indicates that the Pad Low field is present.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e0x08 \u003d PAD_HIGH - b\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eit 4 being set indicates that the Pad High field is present. This bit MUST NOT be set unless the PAD_LOW flag is also set.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field. The total size of a data frame is 8 bytes + length. It is valid to have a zero-length data frame.\u003c/p\u003e\u003cp\u003ePad High: An 8-bit field containing an amount of padding in units of 256 octets. This field is optional and is only present if the PAD_HIGH flag is set. This field, in combination with Pad Low, determines how much padding there is on a frame.\u003c/p\u003e\u003cp\u003ePad Low: An 8-bit field containing an amount of padding in units of single octets. This field is optional and is only present if the PAD_LOW flag is set. This field, in combination with Pad High, determines how much padding there is on a frame.\u003c/p\u003e\u003cp\u003eData: The variable-length data payload; the length was defined in the length field.\u003c/p\u003e\u003cp\u003ePadding: Padding octets that contain no application semantic value. Padding octets MUST be set to zero when sending and ignored when receiving.\u003c/p\u003e\u003cp\u003eData frame processing requirements:\u003c/p\u003e\u003cul\u003e\u003cli\u003eIf an endpoint receives a data frame for a stream-id which is not open and the endpoint has not sent a GOAWAY (Section 2.6.6) frame, it MUST issue a stream error (Section 2.4.2) with the error code INVALID_STREAM for the stream-id.\u003c/li\u003e\u003cli\u003eIf the endpoint which created the stream receives a data frame before receiving a SYN_REPLY on that stream, it is a protocol error, and the recipient MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.\u003c/li\u003e\u003cli\u003eImplementors note: If an endpoint receives multiple data frames for invalid stream-ids, it MAY close the session.\u003c/li\u003e\u003cli\u003ePadding is not excluded from flow control.\u003c/li\u003e\u003cli /\u003e\u003cli\u003eThe total number of padding octets is determined by multiplying the value of the Pad High field by 256 and adding the value of the Pad Low field. Both Pad High and Pad Low fields assume a value of zero if absent. If the length of the padding is greater than the length of the remainder of the frame payload, the recipient MUST treat this as a session error of type PROTOCOL_ERROR.\u003c/li\u003e\u003cli\u003eNote: \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eA frame can be increased in size by one octet by including a Pad Low field with a value of zero.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eUse of padding is a security feature; as such, its use demands some care, see Section 5.5.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.3-Streams\" /\u003e2.3 Streams\u003c/h2\u003e\u003cp\u003eStreams are independent sequences of bi-directional data divided into frames with several properties:\u003c/p\u003e\u003cul\u003e\u003cli\u003eStreams may be created by either the client or server.\u003c/li\u003e\u003cli\u003eStreams optionally carry a set of name/value header pairs.\u003c/li\u003e\u003cli\u003eStreams can concurrently send data interleaved with other streams.\u003c/li\u003e\u003cli\u003eStreams may be cancelled.\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.1-Stream-frames\" /\u003e2.3.1 Stream frames\u003c/h3\u003e\u003cp\u003eSPDY defines 3 control frames to manage the lifecycle of a stream:\u003c/p\u003e\u003cul\u003e\u003cli\u003eSYN_STREAM - Open a new stream\u003c/li\u003e\u003cli\u003eSYN_REPLY - Remote acknowledgement of a new, open stream\u003c/li\u003e\u003cli\u003eRST_STREAM - Close a stream\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.2-Stream-creation\" /\u003e2.3.2 Stream creation\u003c/h3\u003e\u003cp\u003eA stream is created by sending a control frame with the type set to SYN_STREAM (Section 2.6.1). If the server is initiating the stream, the Stream-ID must be even. If the client is initiating the stream, the Stream-ID must be odd. 0 is not a valid Stream-ID. Stream-IDs from each side of the connection must increase monotonically as new streams are created. E.g. Stream 2 may be created after stream 3, but stream 7 must not be created after stream 9. Stream IDs do not wrap: when a client or server cannot create a new stream id without exceeding a 31 bit value, it MUST NOT create a new stream.\u003c/p\u003e\u003cp\u003eThe stream-id MUST increase with each new stream. If an endpoint receives a SYN_STREAM with a stream id which is less than any previously received SYN_STREAM, it MUST issue a session error (Section 2.4.1) with the status PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eIt is a protocol error to send two SYN_STREAMs with the same stream-id. If a recipient receives a second SYN_STREAM for the same stream, it MUST issue a stream error Section (2.4.2) with the status code PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eUpon receipt of a SYN_STREAM, the recipient can reject the stream by sending a stream error (Section 2.4.2) with the error code REFUSED_STREAM. Note, however, that the creating endpoint may have already sent additional frames for that stream which cannot be immediately stopped.\u003c/p\u003e\u003cp\u003eOnce the stream is created, the creator may immediately send HEADERS or DATA frames for that stream, without needing to wait for the recipient to acknowledge.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-2.3.2.1-Unidirectional-streams\" /\u003e2.3.2.1 Unidirectional streams\u003c/h4\u003e\u003cp\u003eWhen an endpoint creates a stream with the FLAG_UNIDIRECTIONAL flag set, it creates a unidirectional stream which the creating endpoint can use to send frames, but the receiving endpoint cannot. The receiving endpoint is implicitly already in the half-closed (Section 2.3.6) state.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-2.3.2.2-Bidirectional-streams\" /\u003e2.3.2.2 Bidirectional streams\u003c/h4\u003e\u003cp\u003eSYN_STREAM frames which do not use the FLAG_UNIDIRECTIONAL flag are bidirectional streams. Both endpoints can send data on a bi-directional stream.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.3-Stream-priority\" /\u003e2.3.3 Stream priority\u003c/h3\u003e\u003cp\u003eThe creator of a stream assigns a priority for that stream. Priority is represented as an integer from 0 to 7. 0 represents the highest priority and 7 represents the lowest priority.\u003c/p\u003e\u003cp\u003eThe sender and recipient SHOULD use best-effort to process streams in the order of highest priority to lowest priority.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.4-Stream-headers\" /\u003e2.3.4 Stream headers\u003c/h3\u003e\u003cp\u003eStreams carry optional sets of name/value pair headers which carry metadata about the stream. After the stream has been created, and as long as the sender is not closed (Section 2.3.7) or half-closed (Section 2.3.6), each side may send HEADERS frame(s) containing the header data. Header data can be sent in multiple HEADERS frames, and HEADERS frames may be interleaved with data frames.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.5-Stream-data-exchange\" /\u003e2.3.5 Stream data exchange\u003c/h3\u003e\u003cp\u003eOnce a stream is created, it can be used to send arbitrary amounts of data. Generally this means that a series of data frames will be sent on the stream until a frame containing the FLAG_FIN flag is set. The FLAG_FIN can be set on a SYN_STREAM (Section 2.6.1), SYN_REPLY (Section 2.6.2), HEADERS (Section 2.6.7) or a DATA (Section 2.2.2) frame. Once the FLAG_FIN has been sent, the stream is considered to be half-closed.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.6-Stream-half-close\" /\u003e2.3.6 Stream half-close\u003c/h3\u003e\u003cp\u003eWhen one side of the stream sends a frame with the FLAG_FIN flag set, the stream is half-closed from that endpoint. The sender of the FLAG_FIN MUST NOT send further frames on that stream. When both sides have half-closed, the stream is closed. Note that WINDOW_UPDATE is metadata about a stream, and is not part of any stream, and as such is still allowed when a stream is half-closed.\u003c/p\u003e\u003cp\u003eIf an endpoint receives a data frame after the stream is half-closed from the sender (e.g. the endpoint has already received a prior frame for the stream with the FIN flag set), it MUST send a RST_STREAM to the sender with the status STREAM_ALREADY_CLOSED.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.7-Stream-close\" /\u003e2.3.7 Stream close\u003c/h3\u003e\u003cp\u003eThere are 3 ways that streams can be terminated:\u003c/p\u003e\u003cul\u003e\u003cli\u003eNormal termination: Normal stream termination occurs when both sender and recipient have half-closed the stream by sending a FLAG_FIN.\u003c/li\u003e\u003cli\u003eAbrupt termination: Either the client or server can send a RST_STREAM control frame at any time. A RST_STREAM contains an error code to indicate the reason for failure. When a RST_STREAM is sent from the stream originator, it indicates a failure to complete the stream and that no further data will be sent on the stream. When a RST_STREAM is sent from the stream recipient, the sender, upon receipt, should stop sending any data on the stream. The stream recipient should be aware that there is a race between data already in transit from the sender and the time the RST_STREAM is received. See Stream Error Handling (Section 2.4.2)\u003c/li\u003e\u003cli\u003eTCP connection teardown: If the TCP connection is torn down while un-closed streams exist, then the endpoint must assume that the stream was abnormally interrupted and may be incomplete.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eIf an endpoint receives a data frame after the stream is closed, it must send a RST_STREAM to the sender with the status PROTOCOL_ERROR.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.4-Error-Handling\" /\u003e2.4 Error Handling\u003c/h2\u003e\u003cp\u003eThe SPDY framing layer has only two types of errors, and they are always handled consistently. Any reference in this specification to \"issue a session error\" refers to Section 2.4.1. Any reference to \"issue a stream error\" refers to Section 2.4.2.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.4.1-Session-Error-Handling\" /\u003e2.4.1 Session Error Handling\u003c/h3\u003e\u003cp\u003eA session error is any error which prevents further processing of the framing layer or which corrupts the session compression state. When a session error occurs, the endpoint encountering the error MUST first send a GOAWAY (Section 2.6.6) frame with the stream id of most recently received stream from the remote endpoint, and the error code for why the session is terminating. After sending the GOAWAY frame, the endpoint MUST close the TCP connection.\u003c/p\u003e\u003cp\u003eNote that the session compression state is dependent upon both endpoints always processing all compressed data. If an endpoint partially processes a frame containing compressed data without updating compression state properly, future control frames which use compression will be always be errored. Implementations SHOULD always try to process compressed data so that errors which could be handled as stream errors do not become session errors.\u003c/p\u003e\u003cp\u003eNote that because this GOAWAY is sent during a session error case, it is possible that the GOAWAY will not be reliably received by the receiving endpoint. It is a best-effort attempt to communicate with the remote about why the session is going down.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.4.2-Stream-Error-Handling\" /\u003e2.4.2 Stream Error Handling\u003c/h3\u003e\u003cp\u003eA stream error is an error related to a specific stream-id which does not affect processing of other streams at the framing layer. Upon a stream error, the endpoint MUST send a RST_STREAM (Section 2.6.3) frame which contains the stream id of the stream where the error occurred and the error status which caused the error. After sending the RST_STREAM, the stream is closed to the sending endpoint. After sending the RST_STREAM, if the sender receives any frames other than a RST_STREAM for that stream id, it will result in sending additional RST_STREAM frames. An endpoint MUST NOT send a RST_STREAM in response to an RST_STREAM, as doing so would lead to RST_STREAM loops. Sending a RST_STREAM does not cause the SPDY session to be closed.\u003c/p\u003e\u003cp\u003eIf an endpoint has multiple RST_STREAM frames to send in succession for the same stream-id and the same error code, it MAY coalesce them into a single RST_STREAM frame. (This can happen if a stream is closed, but the remote sends multiple data frames. There is no reason to send a RST_STREAM for each frame in succession).\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.5-Data-flow\" /\u003e2.5 Data flow\u003c/h2\u003e\u003cp\u003eBecause TCP provides a single stream of data on which SPDY multiplexes multiple logical streams, clients and servers must intelligently interleave data messages for concurrent sessions.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.6-Control-frame-types\" /\u003e2.6 Control frame types\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.1-SYN_STREAM\" /\u003e2.6.1 SYN_STREAM\u003c/h3\u003e\u003cp\u003eThe SYN_STREAM control frame allows the sender to asynchronously create a stream between the endpoints. See Stream Creation (section 2.3.2)\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n|1| version | 1 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n|X| Associated-To-Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Pri|Unused | Slot | |\r\n+-------------------+ |\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003cli\u003e0x02 \u003d FLAG_UNIDIRECTIONAL - a stream created with this flag puts the recipient in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: The length is the number of bytes which follow the length field in the frame. For SYN_STREAM frames, this is 10 bytes plus the length of the compressed Name/Value block.\u003c/p\u003e\u003cp\u003eStream-ID: The 31-bit identifier for this stream. This stream-id will be used in frames which are part of this stream.\u003c/p\u003e\u003cp\u003eAssociated-To-Stream-ID: The 31-bit identifier for a stream which this stream is associated to. If this stream is independent of all other streams, it should be 0.\u003c/p\u003e\u003cp\u003ePriority: A 3-bit priority (Section 2.3.3) field.\u003c/p\u003e\u003cp\u003eUnused: 5 bits of unused space, reserved for future use.\u003c/p\u003e\u003cp\u003eSlot: 8 bits of unused space, reserved for future use. \u003cspan style\u003d\"font-size:10pt\"\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (S\u003c/span\u003eection 2.6.10\u003cspan style\u003d\"font-size:10pt\"\u003e).\u003c/span\u003e\u003c/p\u003e\u003cp\u003eIf an endpoint receives a SYN_STREAM which is larger than the implementation supports, it MAY send a RST_STREAM with error code FRAME_TOO_LARGE. All implementations MUST support the minimum size limits defined in the Control Frames section (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eS\u003c/a\u003eection 2.2.1).\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.2-SYN_REPLY\" /\u003e2.6.2 SYN_REPLY\u003c/h3\u003e\u003cp\u003eSYN_REPLY indicates the acceptance of a stream creation by the recipient of a SYN_STREAM frame.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n|1| version | 2 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: The length is the number of bytes which follow the length field in the frame. For SYN_REPLY frames, this is 4 bytes plus the length of the compressed Name/Value block.\u003c/p\u003e\u003cp\u003eStream-ID: The 31-bit identifier for this stream.\u003c/p\u003e\u003cp\u003eIf an endpoint receives multiple SYN_REPLY frames for the same active stream ID, it MUST issue a stream error (Section 2.4.2) with the error code STREAM_IN_USE.\u003c/p\u003e\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).\u003c/p\u003e\u003cp\u003eIf an endpoint receives a SYN_REPLY which is larger than the implementation supports, it MAY send a RST_STREAM with error code FRAME_TOO_LARGE. All implementations MUST support the minimum size limits defined in the Control Frames section (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eS\u003c/a\u003eection 2.2.1).\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.3-RST_STREAM\" /\u003e2.6.3 RST_STREAM\u003c/h3\u003e\u003cp\u003eThe RST_STREAM frame allows for abnormal termination of a stream. When sent by the creator of a stream, it indicates the creator wishes to cancel the stream. When sent by the recipient of a stream, it indicates an error or that the recipient did not want to accept the stream, so the stream should be closed.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 3 |\r\n+----------------------------------+\r\n| Flags (8) | 8 |\r\n+----------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+----------------------------------+\r\n| Status code |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. RST_STREAM does not define any flags. This value must be 0.\u003c/p\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field. For RST_STREAM control frames, this value is always 8.\u003c/p\u003e\u003cp\u003eStream-ID: The 31-bit identifier for this stream.\u003c/p\u003e\u003cp\u003eStatus code: (32 bits) An indicator for why the stream is being terminated.The following status codes are defined:\u003c/p\u003e\u003cul\u003e\u003cli\u003e1 - PROTOCOL_ERROR. This is a generic error, and should only be used if a more specific error is not available.\u003c/li\u003e\u003cli\u003e2 - INVALID_STREAM. This is returned when a frame is received for a stream which is not active.\u003c/li\u003e\u003cli\u003e3 - REFUSED_STREAM. Indicates that the stream was refused before any processing has been done on the stream.\u003c/li\u003e\u003cli\u003e4 - UNSUPPORTED_VERSION. Indicates that the recipient of a stream does not support the SPDY version requested.\u003c/li\u003e\u003cli\u003e5 - CANCEL. Used by the creator of a stream to indicate that the stream is no longer needed.\u003c/li\u003e\u003cli\u003e6 - INTERNAL_ERROR. This is a generic error which can be used when the implementation has internally failed, not due to anything in the protocol.\u003c/li\u003e\u003cli\u003e7 - FLOW_CONTROL_ERROR. The endpoint detected that its peer violated the flow control protocol.\u003c/li\u003e\u003cli\u003e8 - STREAM_IN_USE. The endpoint received a SYN_REPLY for a stream already open.\u003c/li\u003e\u003cli\u003e9 - STREAM_ALREADY_CLOSED. The endpoint received a data or SYN_REPLY frame for a stream which is half closed.\u003c/li\u003e\u003cli\u003e10 - deprecated/unused.\u003c/li\u003e\u003cli\u003e11 - FRAME_TOO_LARGE. The endpoint received a frame which this implementation could not support. If FRAME_TOO_LARGE is sent for a SYN_STREAM, HEADERS, or SYN_REPLY frame without fully processing the compressed portion of those frames, then the compression state will be out-of-sync with the other endpoint. In this case, senders of FRAME_TOO_LARGE MUST close the session.\u003c/li\u003e\u003cli\u003eNote: 0 is not a valid status code for a RST_STREAM.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eAfter receiving a RST_STREAM on a stream, the recipient must not send additional frames for that stream, and the stream moves into the closed state.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.4-SETTINGS\" /\u003e2.6.4 SETTINGS\u003c/h3\u003e\u003cp\u003eA SETTINGS frame contains a set of id/value pairs for communicating configuration data about how the two endpoints may communicate. SETTINGS frames can be sent at any time by either endpoint, are optionally sent, and are fully asynchronous. When the server is the sender, the sender can request that configuration data be persisted by the client across SPDY sessions and returned to the server in future communications.\u003c/p\u003e\u003cp\u003ePersistence of SETTINGS ID/Value pairs is done on a per origin/IP pair (the \"origin\" is the set of scheme, host, and port from the URI. See \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eRFC6454\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e). That is, when a client connects to a server, and the server persists settings within the client, the client SHOULD return the persisted settings on future connections to the same origin AND IP address and TCP port. Clients MUST NOT request servers to use the persistence features of the SETTINGS frames, and servers MUST ignore persistence related flags sent by a client.\u003c/span\u003e\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 4 |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Number of entries |\r\n+----------------------------------+\r\n| ID/Value Pairs |\r\n| ... |\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp\u003eType: The message type for a SETTINGS message is 4.\u003c/p\u003e\u003cp\u003eFlags: FLAG_SETTINGS_CLEAR_SETTINGS (0x1): When set, the client should clear any previously persisted SETTINGS ID/Value pairs. If this frame contains ID/Value pairs with the FLAG_SETTINGS_PERSIST_VALUE set, then the client will first clear its existing, persisted settings, and then persist the values with the flag set which are contained within this frame. Because persistence is only implemented on the client, this flag can only be used when the sender is the server.\u003c/p\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field. The total size of a SETTINGS frame is 8 bytes + length.\u003c/p\u003e\u003cp\u003eNumber of entries: A 32-bit value representing the number of ID/value pairs in this message.\u003c/p\u003e\u003cp\u003eEach ID/value pair is as follows:\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e +----------------------------------+\r\n | Flags(8) | ID (24 bits) |\r\n +----------------------------------+\r\n | Value (32 bits) |\r\n +----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eFlags: An 8 bit value. Defined Flags:\u003c/p\u003e\u003cul\u003e\u003cli\u003eFLAG_SETTINGS_PERSIST_VALUE (0x1): When set, the sender of this SETTINGS frame is requesting that the recipient persist the ID/Value and return it in future SETTINGS frames sent from the sender to this recipient. Because persistence is only implemented on the client, this flag is only sent by the server.\u003c/li\u003e\u003cli\u003eFLAG_SETTINGS_PERSISTED (0x2): When set, the sender is notifying the recipient that this ID/Value pair was previously sent to the sender by the recipient with the FLAG_SETTINGS_PERSIST_VALUE, and the sender is returning it. Because persistence is only implemented on the client, this flag is only sent by the client.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eID: 24-bits in network byte order. Defined IDs:\u003c/p\u003e\u003cul\u003e\u003cli\u003e1 - SETTINGS_UPLOAD_BANDWIDTH allows the sender to send its expected upload bandwidth on this channel. This number is an estimate. The value should be the integral number of kilobytes per second that the sender predicts as an expected maximum upload channel capacity.\u003c/li\u003e\u003cli\u003e2 - SETTINGS_DOWNLOAD_BANDWIDTH allows the sender to send its expected download bandwidth on this channel. This number is an estimate. The value should be the integral number of kilobytes per second that the sender predicts as an expected maximum download channel capacity.\u003c/li\u003e\u003cli\u003e3 - SETTINGS_ROUND_TRIP_TIME allows the sender to send its expected round-trip-time on this channel. The round trip time is defined as the minimum amount of time to send a control frame from this client to the remote and receive a response. The value is represented in milliseconds.\u003c/li\u003e\u003cli\u003e4 - SETTINGS_MAX_CONCURRENT_STREAMS allows the sender to inform the remote endpoint the maximum number of remote-initiated concurrent streams which it will allow. By default there is no limit. For implementors it is recommended that this value be no smaller than 100.\u003c/li\u003e\u003cli\u003e5 - SETTINGS_CURRENT_CWND allows the sender to inform the remote endpoint of the current TCP CWND value.\u003c/li\u003e\u003cli\u003e6 - SETTINGS_DOWNLOAD_RETRANS_RATE allows the sender to inform the remote endpoint the retransmission rate (bytes retransmitted / total bytes transmitted).\u003c/li\u003e\u003cli\u003e7 - SETTINGS_INITIAL_WINDOW_SIZE allows the sender to inform the remote endpoint the initial window size (in bytes) for new streams.\u003c/li\u003e\u003cli\u003e8 - SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE allows the server to inform the client if the new size of the client certificate vector.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eValue: A 32-bit value.\u003c/p\u003e\u003cp\u003eThe message is intentionally extensible for future information which may improve client-server communications. The sender does not need to send every type of ID/value. It must only send those for which it has accurate values to convey. When multiple ID/value pairs are sent, they should be sent in order of lowest id to highest id. A single SETTINGS frame MUST not contain multiple values for the same ID. If the recipient of a SETTINGS frame discovers multiple values for the same ID, it MUST ignore all values except the first one.\u003c/p\u003e\u003cp\u003eA server may send multiple SETTINGS frames containing different ID/Value pairs. When the same ID/Value is sent twice, the most recent value overrides any previously sent values. If the server sends IDs 1, 2, and 3 with the FLAG_SETTINGS_PERSIST_VALUE in a first SETTINGS frame, and then sends IDs 4 and 5 with the FLAG_SETTINGS_PERSIST_VALUE, when the client returns the persisted state on its next SETTINGS frame, it SHOULD send all 5 settings (1, 2, 3, 4, and 5 in this example) to the server.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.5-PING\" /\u003e2.6.5 PING\u003c/h3\u003e\u003cp\u003eThe PING control frame is a mechanism for measuring a minimal round-trip time from the sender. It can be sent from the client or the server. Recipients of a PING frame should send an identical frame to the sender as soon as possible (if there is other pending data waiting to be sent, PING should take highest priority). Each ping sent by a sender should use a unique ID.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 6 |\r\n+----------------------------------+\r\n| 0 (flags) | 4 (length) |\r\n+----------------------------------|\r\n| 32-bit ID |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp\u003eType: The message type for a PING message is 6.\u003c/p\u003e\u003cp\u003eLength: This frame is always 4 bytes long.\u003c/p\u003e\u003cp\u003eID: A unique ID for this ping, represented as an unsigned 32 bit value. When the client initiates a ping, it must use an odd numbered ID. When the server initiates a ping, it must use an even numbered ping. Use of odd/even IDs is required in order to avoid accidental looping on PINGs (where each side initiates an identical PING at the same time).\u003c/p\u003e\u003cp\u003eNote: If a sender uses all possible PING ids (e.g. has sent all 2^31 possible IDs), it can wrap and start re-using IDs.\u003c/p\u003e\u003cp\u003eIf a server receives an even numbered PING which it did not initiate, it must ignore the PING. If a client receives an odd numbered PING which it did not initiate, it must ignore the PING.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.6-GOAWAY\" /\u003e2.6.6 GOAWAY\u003c/h3\u003e\u003cp\u003eThe GOAWAY control frame is a mechanism to tell the remote side of the connection to stop creating streams on this session. It can be sent from the client or the server. Once sent, the sender will not respond to any new SYN_STREAMs on this session. Recipients of a GOAWAY frame must not send additional streams on this session, although a new session can be established for new streams. The purpose of this message is to allow an endpoint to gracefully stop accepting new streams (perhaps for a reboot or maintenance), while still finishing processing of previously established streams.\u003c/p\u003e\u003cp\u003eThere is an inherent race condition between an endpoint sending SYN_STREAMs and the remote sending a GOAWAY message. To deal with this case, the GOAWAY contains a last-stream-id indicating the stream-id of the last stream which was created on the sending endpoint in this session. If the receiver of the GOAWAY sent new SYN_STREAMs for sessions after this last-stream-id, they were not processed by the server and the receiver may treat the stream as though it had never been created at all (hence the receiver may want to re-create the stream later on a new session).\u003c/p\u003e\u003cp\u003eEndpoints should always send a GOAWAY message before closing a connection so that the remote can know whether a stream has been partially processed or not. (For example, if an HTTP client sends a POST at the same time that a server closes a connection, the client cannot know if the server started to process that POST request if the server does not send a GOAWAY frame to indicate where it stopped working).\u003c/p\u003e\u003cp\u003eAfter sending a GOAWAY message, the sender must ignore all SYN_STREAM frames for new streams, and MUST NOT create any new streams.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 7 |\r\n+----------------------------------+\r\n| 0 (flags) | 8 (length) |\r\n+----------------------------------|\r\n|X| Last-good-stream-ID (31 bits) |\r\n+----------------------------------+\r\n| Status code |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp\u003eType: The message type for a GOAWAY message is 7.\u003c/p\u003e\u003cp\u003eLength: This frame is always 8 bytes long.\u003c/p\u003e\u003cp\u003eLast-good-stream-Id: \u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eThe last stream id which was accepted by the sender of the GOAWAY message\u003c/span\u003e. If no streams were replied to, this value MUST be 0.\u003c/p\u003e\u003cp\u003eStatus: The reason for closing the session.\u003c/p\u003e\u003cul\u003e\u003cli\u003e0 - OK. This is a normal session teardown.\u003c/li\u003e\u003cli\u003e1 - PROTOCOL_ERROR. This is a generic error, and should only be used if a more specific error is not available.\u003c/li\u003e\u003cli\u003e2 - INTERNAL_ERROR. This is a generic error which can be used when the implementation has internally failed, not due to anything in the protocol.\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.7-HEADERS\" /\u003e2.6.7 HEADERS\u003c/h3\u003e\u003cp\u003eThe HEADERS frame augments a stream with additional headers. It may be optionally sent on an existing stream at any time. Specific application of the headers in this frame is application-dependent. The name/value header block within this frame is compressed.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n|1| version | 8 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: An unsigned 24 bit value representing the number of bytes after the length field. The minimum length of the length field is 4 (when the number of name value pairs is 0).\u003c/p\u003e\u003cp\u003eStream-ID: The stream this HEADERS block is associated with.\u003c/p\u003e\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.8-WINDOW_UPDATE\" /\u003e2.6.8 WINDOW_UPDATE\u003c/h3\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eThe WINDOW_UPDATE frame is used to implement flow control.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow control operates at two levels: on each individual stream and on the entire connection.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eBoth types of flow control are hop by hop; that is, only between the two endpoints. Intermediaries do not forward WINDOW_UPDATE frames between dependent connections. However, throttling of data transfer by any receiver can indirectly cause the propagation of flow control information toward the original sender.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow control only applies to frames that are identified as being subject to flow control. Of the frame types defined in this document, this includes only DATA frame. Frames that are exempt from flow control MUST be accepted and processed, unless the receiver is unable to assign resources to handling the frame. A receiver MAY respond with a stream error \u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13px\"\u003e(Section 2.4.2)\u003c/span\u003e or session error \u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13px\"\u003e(Section 2.4.1)\u003c/span\u003e of type FLOW_CONTROL_ERROR if it is unable accept a frame.\u003c/p\u003e\u003cpre\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 9 |\r\n+----------------------------------+\r\n| 0 (flags) | 8 (length) |\r\n+----------------------------------+\r\n|X| Stream-ID (31-bits) |\r\n+----------------------------------+\r\n|X| Delta-Window-Size (31-bits) |\r\n+----------------------------------+\u003c/pre\u003e \u003c/pre\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlags: The flags field is always zero.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eType: The message type for a WINDOW_UPDATE message is 9.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eLength: The length field is always 8 for this frame (there are always 8 bytes after the length field).\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eStream-ID: The stream ID for which this WINDOW_UPDATE control frame applies to, or 0 if applied to connection-level flow control.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eDelta-Window-Size: The additional number of bytes that the sender can transmit in addition to existing remaining window size. The legal range for this field is 1 to 2^31 - 1 (0x7fffffff) bytes.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA receiver that receives a flow controlled frame MUST always account for its contribution against the connection flow control window, unless the receiver treats this as a session error (Section 2.4.1). This is necessary even if the frame is in error. Since the sender counts the frame toward the flow control window, if the receiver does not, the flow control window at sender and receiver can become different.\u003c/p\u003e\u003ch4 style\u003d\"font-family:Times;font-size:medium\"\u003e\u003ca name\u003d\"TOC-The-Flow-Control-Window\" /\u003eThe Flow Control Window\u003c/h4\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow control in SPDY 3.1 is implemented using a window kept by each sender on every stream. The flow control window is a simple integer value that indicates how many bytes of data the sender is permitted to transmit; as such, its size is a measure of the buffering capability of the receiver.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eTwo flow control windows are applicable: the stream flow control window and the connection flow control window. The sender MUST NOT send a flow controlled frame with a length that exceeds the space available in either of the flow control windows advertised by the receiver. Frames with zero length with the END_STREAM flag set (for example, an empty data frame) MAY be sent if there is no available space in either flow control window.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFor flow control calculations, the 8 byte frame header is not counted.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eAfter sending a flow controlled frame, the sender reduces the space available in both windows by the length of the transmitted frame.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eThe receiver of a frame sends a WINDOW_UPDATE frame as it consumes data and frees up space in flow control windows. Separate WINDOW_UPDATE frames are sent for the stream and connection level flow control windows.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA sender that receives a WINDOW_UPDATE frame updates the corresponding window by the amount specified in the frame.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA sender MUST NOT allow a flow control window to exceed 2^31 - 1 bytes. If a sender receives a WINDOW_UPDATE that causes a flow control window to exceed this maximum it MUST terminate either the stream or the connection, as appropriate. For streams, the sender sends a RST_STREAM with the error code of FLOW_CONTROL_ERROR code; for the connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow controlled frames from the sender and WINDOW_UPDATE frames from the receiver are completely asynchronous with respect to each other. This property allows a receiver to aggressively update the window size kept by the sender to prevent streams from stalling.\u003c/p\u003e\u003ch4 style\u003d\"font-family:Times;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Initial-Flow-Control-Window-Size\" /\u003eInitial Flow Control Window Size\u003c/h4\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eWhen a SPDY/3.1 connection is first established, new streams are created with an initial flow control window size of 64KB. The connection flow control window is 64KB bytes. Both endpoints can adjust the initial window size for new streams by including a value for SETTINGS_INITIAL_WINDOW_SIZE in the SETTINGS frame that forms part of the connection header.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003ePrior to receiving a SETTINGS frame that sets a value for SETTINGS_INITIAL_WINDOW_SIZE, an endpoint can only use the default initial window size when sending flow controlled frames. Similarly, the connection flow control window is set to the default initial window size until a WINDOW_UPDATE frame is received.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA SETTINGS frame can alter the initial flow control window size for all current streams. When the value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust the size of all stream flow control windows that it maintains by the difference between the new value and the old value. A SETTINGS frame cannot alter the connection flow control window.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA change to SETTINGS_INITIAL_WINDOW_SIZE could cause the available space in a flow control window to become negative. A sender MUST track the negative flow control window, and MUST NOT send new flow controlled frames until it receives WINDOW_UPDATE frames that cause the flow control window to become positive.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFor example, if the client sends 60KB immediately on connection establishment, and the server sets the initial window size to be 16KB, the client will recalculate the available flow control window to be -44KB on receipt of the SETTINGS frame. The client retains a negative flow control window until WINDOW_UPDATE frames restore the window to being positive, after which the client can resume sending.\u003c/p\u003e\u003ch4 style\u003d\"font-family:Times;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Reducing-the-Stream-Window-Size\" /\u003eReducing the Stream Window Size\u003c/h4\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA receiver that wishes to use a smaller flow control window than the current size can send a new SETTINGS frame. However, the receiver MUST be prepared to receive data that exceeds this window size, since the sender might send data that exceeds the lower limit prior to processing the SETTINGS frame.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA receiver has two options for handling streams that exceed flow control limits:\u003c/p\u003e\u003col style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cli\u003eThe receiver can immediately send RST_STREAM with FLOW_CONTROL_ERROR error code for the affected streams.\u003c/li\u003e\u003cli\u003eThe receiver can accept the streams and tolerate the resulting head of line blocking, sending WINDOW_UPDATE frames as it consumes data.\u003c/li\u003e\u003c/ol\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eIf a receiver decides to accept streams, both sides MUST recompute the available flow control window based on the initial window size sent in the SETTINGS.\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.9-CREDENTIAL\" /\u003e2.6.9 CREDENTIAL\u003c/h3\u003e\u003cp\u003eDEPRECATED.\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.10-Name-Value-Header-Block\" /\u003e2.6.10 Name/Value Header Block\u003c/h3\u003e\u003cp\u003eThe Name/Value Header Block is found in the SYN_STREAM, SYN_REPLY and HEADERS control frames, and shares a common format:\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n| Number of Name/Value pairs (int32) |\r\n+------------------------------------+\r\n| Length of name (int32) |\r\n+------------------------------------+\r\n| Name (string) |\r\n+------------------------------------+\r\n| Length of value (int32) |\r\n+------------------------------------+\r\n| Value (string) |\r\n+------------------------------------+\r\n| (repeats) |\r\n \u003c/pre\u003e\u003cp\u003eNumber of Name/Value pairs: The number of repeating name/value pairs following this field.\u003c/p\u003e\u003cp\u003eList of Name/Value pairs:\u003c/p\u003e\u003cul\u003e\u003cli\u003eLength of Name: a 32-bit value containing the number of octets in the name field. Note that in practice, this length must not exceed 2^24, as that is the maximum size of a SPDY frame.\u003c/li\u003e\u003cli\u003eName: 0 or more octets, 8-bit sequences of data, excluding 0.\u003c/li\u003e\u003cli\u003eLength of Value: a 32-bit value containing the number of octets in the value field. Note that in practice, this length must not exceed 2^24, as that is the maximum size of a SPDY frame.\u003c/li\u003e\u003cli\u003eValue: 0 or more octets, 8-bit sequences of data, excluding 0.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eEach header name must have at least one value. Header names are encoded using the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#ASCII\" rel\u003d\"nofollow\"\u003eUS-ASCII character set\u003c/a\u003e \u003ccite title\u003d\"US-ASCII. Coded Character Set - 7-Bit American Standard Code for Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.\"\u003e[ASCII]\u003c/cite\u003e and must be all lower case. The length of each name must be greater than zero. A recipient of a zero-length name MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.\u003c/p\u003e\u003cp\u003eDuplicate header names are not allowed. To send two identically named headers, send a header with two values, where the values are separated by a single NUL (0) byte. A header value can either be empty (e.g. the length is zero) or it can contain multiple, NUL-separated values, each with length greater than zero. The value never starts nor ends with a NUL character. Recipients of illegal value fields MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-2.6.10.1-Compression\" /\u003e2.6.10.1 Compression\u003c/h4\u003e\u003cp\u003eThe Name/Value Header Block is a section of the SYN_STREAM, SYN_REPLY, and HEADERS frames used to carry header meta-data. This block is always compressed using zlib compression. Within this specification, any reference to 'zlib' is referring to the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC1950\" rel\u003d\"nofollow\"\u003eZLIB Compressed Data Format Specification Version 3.3 as part of RFC1950.\u003c/a\u003e\u003c/p\u003e\u003cp\u003eFor each HEADERS compression instance, the initial state is initialized using the following \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#UDELCOMPRESSION\" rel\u003d\"nofollow\"\u003edictionary\u003c/a\u003e \u003ccite title\u003d\"A Methodology to Derive SPDY’s Initial Dictionary for Zlib Compression\"\u003e[UDELCOMPRESSION]\u003c/cite\u003e:\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003econst unsigned char SPDY_dictionary_txt[] \u003d {\r\n\t0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, \\\\ - - - - o p t i\r\n\t0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, \\\\ o n s - - - - h\r\n\t0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, \\\\ e a d - - - - p\r\n\t0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, \\\\ o s t - - - - p\r\n\t0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, \\\\ u t - - - - d e\r\n\t0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, \\\\ l e t e - - - -\r\n\t0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, \\\\ t r a c e - - -\r\n\t0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, \\\\ - a c c e p t -\r\n\t0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, \\\\ - - - a c c e p\r\n\t0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\\\ t - c h a r s e\r\n\t0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, \\\\ t - - - - a c c\r\n\t0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\\\ e p t - e n c o\r\n\t0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, \\\\ d i n g - - - -\r\n\t0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, \\\\ a c c e p t - l\r\n\t0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, \\\\ a n g u a g e -\r\n\t0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, \\\\ - - - a c c e p\r\n\t0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, \\\\ t - r a n g e s\r\n\t0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, \\\\ - - - - a g e -\r\n\t0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, \\\\ - - - a l l o w\r\n\t0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, \\\\ - - - - a u t h\r\n\t0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, \\\\ o r i z a t i o\r\n\t0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, \\\\ n - - - - c a c\r\n\t0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, \\\\ h e - c o n t r\r\n\t0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, \\\\ o l - - - - c o\r\n\t0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, \\\\ n n e c t i o n\r\n\t0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, \\\\ e n t - b a s e\r\n\t0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\\\ e n t - e n c o\r\n\t0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, \\\\ d i n g - - - -\r\n\t0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, \\\\ c o n t e n t -\r\n\t0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, \\\\ l a n g u a g e\r\n\t0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, \\\\ e n t - l e n g\r\n\t0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, \\\\ t h - - - - c o\r\n\t0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, \\\\ n t e n t - l o\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\\\ c a t i o n - -\r\n\t0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\\\ - - c o n t e n\r\n\t0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, \\\\ t - m d 5 - - -\r\n\t0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, \\\\ - c o n t e n t\r\n\t0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, \\\\ - r a n g e - -\r\n\t0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\\\ - - c o n t e n\r\n\t0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, \\\\ t - t y p e - -\r\n\t0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, \\\\ - - d a t e - -\r\n\t0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, \\\\ - - e t a g - -\r\n\t0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, \\\\ - - e x p e c t\r\n\t0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, \\\\ - - - - e x p i\r\n\t0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, \\\\ r e s - - - - f\r\n\t0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, \\\\ r o m - - - - h\r\n\t0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, \\\\ o s t - - - - i\r\n\t0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, \\\\ f - m a t c h -\r\n\t0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, \\\\ - - - i f - m o\r\n\t0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, \\\\ d i f i e d - s\r\n\t0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, \\\\ i n c e - - - -\r\n\t0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, \\\\ i f - n o n e -\r\n\t0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, \\\\ m a t c h - - -\r\n\t0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, \\\\ - i f - r a n g\r\n\t0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, \\\\ e - - - - i f -\r\n\t0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, \\\\ u n m o d i f i\r\n\t0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, \\\\ e d - s i n c e\r\n\t0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, \\\\ - - - - l a s t\r\n\t0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, \\\\ - m o d i f i e\r\n\t0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, \\\\ d - - - - l o c\r\n\t0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, \\\\ a t i o n - - -\r\n\t0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, \\\\ - m a x - f o r\r\n\t0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, \\\\ w a r d s - - -\r\n\t0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, \\\\ - p r a g m a -\r\n\t0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, \\\\ - - - p r o x y\r\n\t0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, \\\\ - a u t h e n t\r\n\t0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, \\\\ i c a t e - - -\r\n\t0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, \\\\ - p r o x y - a\r\n\t0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, \\\\ u t h o r i z a\r\n\t0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, \\\\ t i o n - - - -\r\n\t0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, \\\\ r a n g e - - -\r\n\t0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, \\\\ - r e f e r e r\r\n\t0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, \\\\ - - - - r e t r\r\n\t0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, \\\\ y - a f t e r -\r\n\t0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, \\\\ - - - s e r v e\r\n\t0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, \\\\ r - - - - t e -\r\n\t0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, \\\\ - - - t r a i l\r\n\t0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, \\\\ e r - - - - t r\r\n\t0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, \\\\ a n s f e r - e\r\n\t0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, \\\\ n c o d i n g -\r\n\t0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, \\\\ - - - u p g r a\r\n\t0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, \\\\ d e - - - - u s\r\n\t0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, \\\\ e r - a g e n t\r\n\t0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, \\\\ - - - - v a r y\r\n\t0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, \\\\ - - - - v i a -\r\n\t0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, \\\\ - - - w a r n i\r\n\t0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, \\\\ n g - - - - w w\r\n\t0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, \\\\ w - a u t h e n\r\n\t0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, \\\\ t i c a t e - -\r\n\t0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, \\\\ - - m e t h o d\r\n\t0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, \\\\ - - - - g e t -\r\n\t0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, \\\\ - - - s t a t u\r\n\t0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, \\\\ s - - - - 2 0 0\r\n\t0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, \\\\ - O K - - - - v\r\n\t0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\\\ e r s i o n - -\r\n\t0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, \\\\ - - H T T P - 1\r\n\t0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, \\\\ - 1 - - - - u r\r\n\t0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, \\\\ l - - - - p u b\r\n\t0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, \\\\ l i c - - - - s\r\n\t0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, \\\\ e t - c o o k i\r\n\t0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, \\\\ e - - - - k e e\r\n\t0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, \\\\ p - a l i v e -\r\n\t0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, \\\\ - - - o r i g i\r\n\t0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, \\\\ n 1 0 0 1 0 1 2\r\n\t0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, \\\\ 0 1 2 0 2 2 0 5\r\n\t0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, \\\\ 2 0 6 3 0 0 3 0\r\n\t0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, \\\\ 2 3 0 3 3 0 4 3\r\n\t0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, \\\\ 0 5 3 0 6 3 0 7\r\n\t0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, \\\\ 4 0 2 4 0 5 4 0\r\n\t0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, \\\\ 6 4 0 7 4 0 8 4\r\n\t0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, \\\\ 0 9 4 1 0 4 1 1\r\n\t0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, \\\\ 4 1 2 4 1 3 4 1\r\n\t0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, \\\\ 4 4 1 5 4 1 6 4\r\n\t0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, \\\\ 1 7 5 0 2 5 0 4\r\n\t0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, \\\\ 5 0 5 2 0 3 - N\r\n\t0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, \\\\ o n - A u t h o\r\n\t0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, \\\\ r i t a t i v e\r\n\t0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, \\\\ - I n f o r m a\r\n\t0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, \\\\ t i o n 2 0 4 -\r\n\t0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, \\\\ N o - C o n t e\r\n\t0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, \\\\ n t 3 0 1 - M o\r\n\t0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, \\\\ v e d - P e r m\r\n\t0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, \\\\ a n e n t l y 4\r\n\t0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, \\\\ 0 0 - B a d - R\r\n\t0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, \\\\ e q u e s t 4 0\r\n\t0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, \\\\ 1 - U n a u t h\r\n\t0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, \\\\ o r i z e d 4 0\r\n\t0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, \\\\ 3 - F o r b i d\r\n\t0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, \\\\ d e n 4 0 4 - N\r\n\t0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, \\\\ o t - F o u n d\r\n\t0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, \\\\ 5 0 0 - I n t e\r\n\t0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, \\\\ r n a l - S e r\r\n\t0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, \\\\ v e r - E r r o\r\n\t0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, \\\\ r 5 0 1 - N o t\r\n\t0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, \\\\ - I m p l e m e\r\n\t0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, \\\\ n t e d 5 0 3 -\r\n\t0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, \\\\ S e r v i c e -\r\n\t0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, \\\\ U n a v a i l a\r\n\t0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, \\\\ b l e J a n - F\r\n\t0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, \\\\ e b - M a r - A\r\n\t0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, \\\\ p r - M a y - J\r\n\t0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, \\\\ u n - J u l - A\r\n\t0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, \\\\ u g - S e p t -\r\n\t0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, \\\\ O c t - N o v -\r\n\t0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, \\\\ D e c - 0 0 - 0\r\n\t0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, \\\\ 0 - 0 0 - M o n\r\n\t0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, \\\\ - - T u e - - W\r\n\t0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, \\\\ e d - - T h u -\r\n\t0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, \\\\ - F r i - - S a\r\n\t0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, \\\\ t - - S u n - -\r\n\t0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, \\\\ G M T c h u n k\r\n\t0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, \\\\ e d - t e x t -\r\n\t0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, \\\\ h t m l - i m a\r\n\t0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, \\\\ g e - p n g - i\r\n\t0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, \\\\ m a g e - j p g\r\n\t0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, \\\\ - i m a g e - g\r\n\t0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\\\ i f - a p p l i\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\\\ c a t i o n - x\r\n\t0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\\\ m l - a p p l i\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\\\ c a t i o n - x\r\n\t0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, \\\\ h t m l - x m l\r\n\t0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, \\\\ - t e x t - p l\r\n\t0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, \\\\ a i n - t e x t\r\n\t0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, \\\\ - j a v a s c r\r\n\t0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, \\\\ i p t - p u b l\r\n\t0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, \\\\ i c p r i v a t\r\n\t0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, \\\\ e m a x - a g e\r\n\t0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, \\\\ - g z i p - d e\r\n\t0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, \\\\ f l a t e - s d\r\n\t0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\\\ c h c h a r s e\r\n\t0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, \\\\ t - u t f - 8 c\r\n\t0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, \\\\ h a r s e t - i\r\n\t0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, \\\\ s o - 8 8 5 9 -\r\n\t0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, \\\\ 1 - u t f - - -\r\n\t0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e \\\\ - e n q - 0 -\r\n};\r\n \u003c/pre\u003e\u003cp\u003eThe entire contents of the name/value header block is compressed using zlib. There is a single zlib stream for all name value pairs in one direction on a connection. SPDY uses a SYNC_FLUSH between each compressed frame.\u003c/p\u003e\u003cp\u003eImplementation notes: the compression engine can be tuned to favor speed or size. Optimizing for size increases memory use and CPU consumption. Because header blocks are generally small, implementors may want to reduce the window-size of the compression engine from the default 15bits (a 32KB window) to more like 11bits (a 2KB window). The exact setting is chosen by the compressor, the decompressor will work with any setting.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-3.-HTTP-Layering-over-SPDY\" /\u003e3. HTTP Layering over SPDY\u003c/h1\u003e\u003cp\u003eSPDY is intended to be as compatible as possible with current web-based applications. This means that, from the perspective of the server business logic or application API, the features of HTTP are unchanged. To achieve this, all of the application request and response header semantics are preserved, although the syntax of conveying those semantics has changed. Thus, the rules from the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2616\" rel\u003d\"nofollow\"\u003eHTTP/1.1 specification in RFC2616\u003c/a\u003e apply with the changes in the sections below.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.1-Connection-Management\" /\u003e3.1 Connection Management\u003c/h2\u003e\u003cp\u003eClients SHOULD NOT open more than one SPDY session to a given \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003eorigin\u003c/a\u003e concurrently.\u003c/p\u003e\u003cp\u003eNote that it is possible for one SPDY session to be finishing (e.g. a GOAWAY message has been sent, but not all streams have finished), while another SPDY session is starting.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.1.1-Use-of-GOAWAY\" /\u003e3.1.1 Use of GOAWAY\u003c/h3\u003e\u003cp\u003eSPDY provides a GOAWAY message which can be used when closing a connection from either the client or server. Without a server GOAWAY message, HTTP has a race condition where the client sends a request (a new SYN_STREAM) just as the server is closing the connection, and the client cannot know if the server received the stream or not. By using the last-stream-id in the GOAWAY, servers can indicate to the client if a request was processed or not.\u003c/p\u003e\u003cp\u003eNote that some servers will choose to send the GOAWAY and immediately terminate the connection without waiting for active streams to finish. The client will be able to determine this because SPDY streams are determinstically closed. This abrupt termination will force the client to heuristically decide whether to retry the pending requests. Clients always need to be capable of dealing with this case because they must deal with accidental connection termination cases, which are the same as the server never having sent a GOAWAY.\u003c/p\u003e\u003cp\u003eMore sophisticated servers will use GOAWAY to implement a graceful teardown. They will send the GOAWAY and provide some time for the active streams to finish before terminating the connection.\u003c/p\u003e\u003cp\u003eIf a SPDY client closes the connection, it should also send a GOAWAY message. This allows the server to know if any server-push streams were received by the client.\u003c/p\u003e\u003cp\u003eIf the endpoint closing the connection has not received any SYN_STREAMs from the remote, the GOAWAY will contain a last-stream-id of 0.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.2-HTTP-Request-Response\" /\u003e3.2 HTTP Request/Response\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.1-Request\" /\u003e3.2.1 Request\u003c/h3\u003e\u003cp\u003eThe client initiates a request by sending a SYN_STREAM frame. For requests which do not contain a body, the SYN_STREAM frame MUST set the FLAG_FIN, indicating that the client intends to send no further data on this stream. For requests which do contain a body, the SYN_STREAM will not contain the FLAG_FIN, and the body will follow the SYN_STREAM in a series of DATA frames. The last DATA frame will set the FLAG_FIN to indicate the end of the body.\u003c/p\u003e\u003cp\u003eThe SYN_STREAM Name/Value section will contain all of the HTTP headers which are associated with an HTTP request. The header block in SPDY is mostly unchanged from today's HTTP header block, with the following differences:\u003c/p\u003e\u003cul\u003e\u003cli\u003eThe first line of the request is unfolded into name/value pairs like other HTTP headers and MUST be present:\u003cul\u003e\u003cli\u003e\":method\" - the HTTP method for this request (e.g. \"GET\", \"POST\", \"HEAD\", etc)\u003c/li\u003e\u003cli\u003e\":path\" - the url-path for this url with \"/\" prefixed. (See \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC3986\" rel\u003d\"nofollow\"\u003eRFC3986\u003c/a\u003e). For example, for \"http://www.google.com/search?q\u003ddogs\" the path would be \"/search?q\u003ddogs\".\u003c/li\u003e\u003cli\u003e\":version\" - the HTTP version of this request (e.g. \"HTTP/1.1\")\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003eIn addition, the following two name/value pairs must also be present in every request:\u003cul\u003e\u003cli\u003e\":host\" - the hostport (See \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC1738\" rel\u003d\"nofollow\"\u003eRFC1738\u003c/a\u003e) portion of the URL for this request (e.g. \"www.google.com:1234\"). This header is the same as the HTTP 'Host' header.\u003c/li\u003e\u003cli\u003e\":scheme\" - the scheme portion of the URL for this request (e.g. \"https\"))\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003eHeader names are all lowercase.\u003c/li\u003e\u003cli\u003eThe Connection, Host, Keep-Alive, Proxy-Connection, and Transfer-Encoding headers are not valid and MUST not be sent.\u003c/li\u003e\u003cli\u003eUser-agents MUST support gzip compression. Regardless of the Accept-Encoding sent by the user-agent, the server may always send content encoded with gzip or deflate encoding.\u003c/li\u003e\u003cli\u003eIf a server receives a request where the sum of the data frame payload lengths does not equal the size of the Content-Length header, the server MUST return a 400 (Bad Request) error.\u003c/li\u003e\u003cli\u003ePOST-specific changes:\u003cul\u003e\u003cli\u003eAlthough POSTs are inherently chunked, POST requests SHOULD also be accompanied by a Content-Length header. There are two reasons for this: First, it assists with upload progress meters for an improved user experience. But second, we know from early versions of SPDY that failure to send a content length header is incompatible with many existing HTTP server implementations. Existing user-agents do not omit the Content-Length header, and server implementations have come to depend upon this.\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eThe user-agent is free to prioritize requests as it sees fit. If the user-agent cannot make progress without receiving a resource, it should attempt to raise the priority of that resource. Resources such as images, SHOULD generally use the lowest priority.\u003c/p\u003e\u003cp\u003eIf a client sends a SYN_STREAM without all of the method, host, path, scheme, and version headers, the server MUST reply with a HTTP 400 Bad Request reply.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.2-Response\" /\u003e3.2.2 Response\u003c/h3\u003e\u003cp\u003eThe server responds to a client request with a SYN_REPLY frame. Symmetric to the client's upload stream, server will send data after the SYN_REPLY frame via a series of DATA frames, and the last data frame will contain the FLAG_FIN to indicate successful end-of-stream. If a response (like a 202 or 204 response) contains no body, the SYN_REPLY frame may contain the FLAG_FIN flag to indicate no further data will be sent on the stream.\u003c/p\u003e\u003cul\u003e\u003cli\u003eThe response status line is unfolded into name/value pairs like other HTTP headers and must be present:\u003cul\u003e\u003cli\u003e\":status\" - The HTTP response status code (e.g. \"200\" or \"200 OK\")\u003c/li\u003e\u003cli\u003e\":version\" - The HTTP response version (e.g. \"HTTP/1.1\")\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003eAll header names must be lowercase.\u003c/li\u003e\u003cli\u003eThe Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding headers are not valid and MUST not be sent.\u003c/li\u003e\u003cli\u003eResponses MAY be accompanied by a Content-Length header for advisory purposes. (e.g. for UI progress meters)\u003c/li\u003e\u003cli\u003eIf a client receives a response where the sum of the data frame payload lengths does not equal the size of the Content-Length header, the client MUST ignore the content length header.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eIf a client receives a SYN_REPLY without a status or without a version header, the client must reply with a RST_STREAM frame indicating a PROTOCOL ERROR.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.3-Authentication\" /\u003e3.2.3 Authentication\u003c/h3\u003e\u003cp\u003eWhen a client sends a request to an origin server that requires authentication, the server can reply with a \"401 Unauthorized\" response, and include a WWW-Authenticate challenge header that defines the authentication scheme to be used. The client then retries the request with an Authorization header appropriate to the specified authentication scheme.\u003c/p\u003e\u003cp\u003eThere are four options for proxy authentication, Basic, Digest, NTLM and Negotiate (SPNEGO). The first two options were defined in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2617\" rel\u003d\"nofollow\"\u003eRFC2617\u003c/a\u003e, and are stateless. The second two options were developed by Microsoft and specified in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC4559\" rel\u003d\"nofollow\"\u003eRFC4559\u003c/a\u003e, and are stateful; otherwise known as multi-round authentication, or connection authentication.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-3.2.3.1-Stateless-Authentication\" /\u003e3.2.3.1 Stateless Authentication\u003c/h4\u003e\u003cp\u003eStateless Authentication over SPDY is identical to how it is performed over HTTP. If multiple SPDY streams are concurrently sent to a single server, each will authenticate independently, similar to how two HTTP connections would independently authenticate to a proxy server.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-3.2.3.2-Stateful-Authentication\" /\u003e3.2.3.2 Stateful Authentication\u003c/h4\u003e\u003cp\u003eUnfortunately, the stateful authentication mechanisms were implemented and defined in a such a way that directly violates RFC2617 - they do not include a \"realm\" as part of the request. This is problematic in SPDY because it makes it impossible for a client to disambiguate two concurrent server authentication challenges.\u003c/p\u003e\u003cp\u003eTo deal with this case, SPDY servers using Stateful Authentication MUST implement one of two changes:\u003c/p\u003e\u003cul\u003e\u003cli\u003eServers can add a \"realm\u003d\u0026lt;desired realm\u0026gt;\" header so that the two authentication requests can be disambiguated and run concurrently. Unfortunately, given how these mechanisms work, this is probably not practical.\u003c/li\u003e\u003cli\u003eUpon sending the first stateful challenge response, the server MUST buffer and defer all further frames which are not part of completing the challenge until the challenge has completed. Completing the authentication challenge may take multiple round trips. Once the client receives a \"401 Authenticate\" response for a stateful authentication type, it MUST stop sending new requests to the server until the authentication has completed by receiving a non-401 response on at least one stream.\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.3-Server-Push-Transactions\" /\u003e3.3 Server Push Transactions\u003c/h2\u003e\u003cp\u003eSPDY enables a server to send multiple replies to a client for a single request. The rationale for this feature is that sometimes a server knows that it will need to send multiple resources in response to a single request. Without server push features, the client must first download the primary resource, then discover the secondary resource(s), and request them. Pushing of resources avoids the round-trip delay, but also creates a potential race where a server can be pushing content which a user-agent is in the process of requesting. The following mechanics attempt to prevent the race condition while enabling the performance benefit.\u003c/p\u003e\u003cp\u003eBrowsers receiving a pushed response MUST validate that the server is authorized to push the URL using the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003ebrowser same-origin\u003c/a\u003e policy. For example, a SPDY connection to www.foo.com is generally not permitted to push a response for www.evil.com.\u003c/p\u003e\u003cp\u003eIf the browser accepts a pushed response (e.g. it does not send a RST_STREAM), the browser MUST attempt to cache the pushed response in same way that it would cache any other response. This means validating the response headers and inserting into the cache.\u003c/p\u003e\u003cp\u003eBecause pushed responses have no request, they have no request headers associated with them. At the framing layer, SPDY pushed streams contain an \"associated-stream-id\" which indicates the requested stream for which the pushed stream is related. The pushed stream inherits all of the headers from the associated-stream-id with the exception of \":host\", \":scheme\", and \":path\", which are provided as part of the pushed response stream headers. The browser MUST store these inherited and implied request headers with the cached resource.\u003c/p\u003e\u003cp\u003eImplementation note: With server push, it is theoretically possible for servers to push unreasonable amounts of content or resources to the user-agent. Browsers MUST implement throttles to protect against unreasonable push attacks.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.3.1-Server-implementation\" /\u003e3.3.1 Server implementation\u003c/h3\u003e\u003cp\u003eWhen the server intends to push a resource to the user-agent, it opens a new stream by sending a unidirectional SYN_STREAM. The SYN_STREAM MUST include an Associated-To-Stream-ID, and MUST set the FLAG_UNIDIRECTIONAL flag. The SYN_STREAM MUST include headers for \":scheme\", \":host\", \":path\", which represent the URL for the resource being pushed. Subsequent headers may follow in HEADERS frames. The purpose of the association is so that the user-agent can differentiate which request induced the pushed stream; without it, if the user-agent had two tabs open to the same page, each pushing unique content under a fixed URL, the user-agent would not be able to differentiate the requests.\u003c/p\u003e\u003cp\u003eThe Associated-To-Stream-ID must be the ID of an existing, open stream. The reason for this restriction is to have a clear endpoint for pushed content. If the user-agent requested a resource on stream 11, the server replies on stream 11. It can push any number of additional streams to the client before sending a FLAG_FIN on stream 11. However, once the originating stream is closed no further push streams may be associated with it. The pushed streams do not need to be closed (FIN set) before the originating stream is closed, they only need to be created before the originating stream closes.\u003c/p\u003e\u003cp\u003eIt is illegal for a server to push a resource with the Associated-To-Stream-ID of 0.\u003c/p\u003e\u003cp\u003eTo minimize race conditions with the client, the SYN_STREAM for the pushed resources MUST be sent prior to sending any content which could allow the client to discover the pushed resource and request it.\u003c/p\u003e\u003cp\u003eThe server MUST only push resources which would have been returned from a GET request.\u003c/p\u003e\u003cp\u003eNote: If the server does not have all of the Name/Value Response headers available at the time it issues the HEADERS frame for the pushed resource, it may later use an additional HEADERS frame to augment the name/value pairs to be associated with the pushed stream. The subsequent HEADERS frame(s) must not contain a header for ':host', ':scheme', or ':path' (e.g. the server can't change the identity of the resource to be pushed). The HEADERS frame must not contain duplicate headers with a previously sent HEADERS frame. The server must send a HEADERS frame including the scheme/host/port headers before sending any data frames on the stream.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.3.2-Client-implementation\" /\u003e3.3.2 Client implementation\u003c/h3\u003e\u003cp\u003eWhen fetching a resource the client has 3 possibilities:\u003c/p\u003e\u003cul\u003e\u003cli\u003ethe resource is not being pushed\u003c/li\u003e\u003cli\u003ethe resource is being pushed, but the data has not yet arrived\u003c/li\u003e\u003cli\u003ethe resource is being pushed, and the data has started to arrive\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eWhen a SYN_STREAM and HEADERS frame which contains an Associated-To-Stream-ID is received, the client must not issue GET requests for the resource in the pushed stream, and instead wait for the pushed stream to arrive.\u003c/p\u003e\u003cp\u003eIf a client receives a server push stream with stream-id 0, it MUST issue a session error (Section 2.4.2) with the status code PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eWhen a client receives a SYN_STREAM from the server without a the ':host', ':scheme', and ':path' headers in the Name/Value section, it MUST reply with a RST_STREAM with error code HTTP_PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eTo cancel individual server push streams, the client can issue a stream error (Section 2.4.2) with error code CANCEL. Upon receipt, the server MUST stop sending on this stream immediately (this is an Abrupt termination).\u003c/p\u003e\u003cp\u003eTo cancel all server push streams related to a request, the client may issue a stream error (Section 2.4.2) with error code CANCEL on the associated-stream-id. By cancelling that stream, the server MUST immediately stop sending frames for any streams  with in-association-to for the original stream.\u003c/p\u003e\u003cp\u003eIf the server sends a HEADER frame containing duplicate headers with a previous HEADERS frame for the same stream, the client must issue a stream error (Section 2.4.2) with error code PROTOCOL ERROR.\u003c/p\u003e\u003cp\u003eIf the server sends a HEADERS frame after sending a data frame for the same stream, the client MAY ignore the HEADERS frame. Ignoring the HEADERS frame after a data frame prevents handling of HTTP's trailing headers (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.40).\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-4.-Design-Rationale-and-Notes\" /\u003e4. Design Rationale and Notes\u003c/h1\u003e\u003cp\u003eAuthors' notes: The notes in this section have no bearing on the SPDY protocol as specified within this document, and none of these notes should be considered authoritative about how the protocol works. However, these notes may prove useful in future debates about how to resolve protocol ambiguities or how to evolve the protocol going forward. They may be removed before the final draft.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.1-Separation-of-Framing-Layer-and-Application-Layer\" /\u003e4.1 Separation of Framing Layer and Application Layer\u003c/h2\u003e\u003cp\u003eReaders may note that this specification sometimes blends the framing layer (Section 2) with requirements of a specific application - HTTP (Section 3). This is reflected in the request/response nature of the streams, the definition of the HEADERS and compression contexts which are very similar to HTTP, and other areas as well.\u003c/p\u003e\u003cp\u003eThis blending is intentional - the primary goal of this protocol is to create a low-latency protocol for use with HTTP. Isolating the two layers is convenient for description of the protocol and how it relates to existing HTTP implementations. However, the ability to reuse the SPDY framing layer is a non goal.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.2-Error-handling---Framing-Layer\" /\u003e4.2 Error handling - Framing Layer\u003c/h2\u003e\u003cp\u003eError handling at the SPDY layer splits errors into two groups: Those that affect an individual SPDY stream, and those that do not.\u003c/p\u003e\u003cp\u003eWhen an error is confined to a single stream, but general framing is in tact, SPDY attempts to use the RST_STREAM as a mechanism to invalidate the stream but move forward without aborting the connection altogether.\u003c/p\u003e\u003cp\u003eFor errors occuring outside of a single stream context, SPDY assumes the entire session is hosed. In this case, the endpoint detecting the error should initiate a connection close.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.3-One-Connection-Per-Domain\" /\u003e4.3 One Connection Per Domain\u003c/h2\u003e\u003cp\u003eSPDY attempts to use fewer connections than other protocols have traditionally used. The rationale for this behavior is because it is very difficult to provide a consistent level of service (e.g. TCP slow-start), prioritization, or optimal compression when the client is connecting to the server through multiple channels.\u003c/p\u003e\u003cp\u003eThrough lab measurements, we have seen consistent latency benefits by using fewer connections from the client. The overall number of packets sent by SPDY can be as much as 40% less than HTTP. Handling large numbers of concurrent connections on the server also does become a scalability problem, and SPDY reduces this load.\u003c/p\u003e\u003cp\u003eThe use of multiple connections is not without benefit, however. Because SPDY multiplexes multiple, independent streams onto a single stream, it creates a potential for head-of-line blocking problems at the transport level. In tests so far, the negative effects of head-of-line blocking (especially in the presence of packet loss) is outweighed by the benefits of compression and prioritization.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.4-Fixed-vs-Variable-Length-Fields\" /\u003e4.4 Fixed vs Variable Length Fields\u003c/h2\u003e\u003cp\u003eSPDY favors use of fixed length 32bit fields in cases where smaller, variable length encodings could have been used. To some, this seems like a tragic waste of bandwidth. SPDY choses the simple encoding for speed and simplicity.\u003c/p\u003e\u003cp\u003eThe goal of SPDY is to reduce latency on the network. The overhead of SPDY frames is generally quite low. Each data frame is only an 8 byte overhead for a 1452 byte payload (~0.6%). At the time of this writing, bandwidth is already plentiful, and there is a strong trend indicating that bandwidth will continue to increase. With an average worldwide bandwidth of 1Mbps, and assuming that a variable length encoding could reduce the overhead by 50%, the latency saved by using a variable length encoding would be less than 100 nanoseconds. More interesting are the effects when the larger encodings force a packet boundary, in which case a round-trip could be induced. However, by addressing other aspects of SPDY and TCP interactions, we believe this is completely mitigated.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.5-Compression-Context-s-\" /\u003e4.5 Compression Context(s)\u003c/h2\u003e\u003cp\u003eWhen isolating the compression contexts used for communicating with multiple origins, we had a few choices to make. We could have maintained a map (or list) of compression contexts usable for each origin. The basic case is easy - each HEADERS frame would need to identify the context to use for that frame. However, compression contexts are not cheap, so the lifecycle of each context would need to be bounded. For proxy servers, where we could churn through many contexts, this would be a concern. We considered using a static set of contexts, say 16 of them, which would bound the memory use. We also considered dynamic contexts, which could be created on the fly, and would need to be subsequently destroyed. All of these are complicated, and ultimately we decided that such a mechanism creates too many problems to solve.\u003c/p\u003e\u003cp\u003eAlternatively, we've chosen the simple approach, which is to simply provide a flag for resetting the compression context. For the common case (no proxy), this fine because most requests are to the same origin and we never need to reset the context. For cases where we are using two different origins over a single SPDY session, we simply reset the compression state between each transition.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.6-Unidirectional-streams\" /\u003e4.6 Unidirectional streams\u003c/h2\u003e\u003cp\u003eMany readers notice that unidirectional streams are both a bit confusing in concept and also somewhat redundant. If the recipient of a stream doesn't wish to send data on a stream, it could simply send a SYN_REPLY with the FLAG_FIN bit set. The FLAG_UNIDIRECTIONAL is, therefore, not necessary.\u003c/p\u003e\u003cp\u003eIt is true that we don't need the UNIDIRECTIONAL markings. It is added because it avoids the recipient of pushed streams from needing to send a set of empty frames (e.g. the SYN_STREAM w/ FLAG_FIN) which otherwise serve no purpose.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.7-Data-Compression\" /\u003e4.7 Data Compression\u003c/h2\u003e\u003cp\u003eGeneric compression of data portion of the streams (as opposed to compression of the headers) without knowing the content of the stream is redundant. There is no value in compressing a stream which is already compressed. Because of this, SPDY initially allowed data compression to be optional. We included it because study of existing websites shows that many sites are not using compression as they should, and users suffer because of it. We wanted a mechanism where, at the SPDY layer, site administrators could simply force compression - it is better to compress twice than to not compress.\u003c/p\u003e\u003cp\u003eOverall, however, with this feature being optional and sometimes redundant, it was unclear if it was useful at all. We removed it from the specification.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.8-Server-Push\" /\u003e4.8 Server Push\u003c/h2\u003e\u003cp\u003eA subtle but important point is that server push streams must be declared before the associated stream is closed. The reason for this is so that proxies have a lifetime for which they can discard information about previous streams. If a pushed stream could associate itself with an already-closed stream, then endpoints would not have a specific lifecycle for when they could disavow knowledge of the streams which went before.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-5.-Security-Considerations\" /\u003e5. Security Considerations\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.1-Use-of-Same-origin-constraints\" /\u003e5.1 Use of Same-origin constraints\u003c/h2\u003e\u003cp\u003eThis specification uses the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003esame-origin policy\u003c/a\u003e in all cases where verification of content is required.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.2-HTTP-Headers-and-SPDY-Headers\" /\u003e5.2 HTTP Headers and SPDY Headers\u003c/h2\u003e\u003cp\u003eAt the application level, HTTP uses name/value pairs in its headers. Because SPDY merges the existing HTTP headers with SPDY headers, there is a possibility that some HTTP applications already use a particular header name. To avoid any conflicts, all headers introduced for layering HTTP over SPDY are prefixed with \":\". \":\" is not a valid sequence in HTTP header naming, preventing any possible conflict.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.3-Cross-Protocol-Attacks\" /\u003e5.3 Cross-Protocol Attacks\u003c/h2\u003e\u003cp\u003eBy utilizing TLS, we believe that SPDY introduces no new cross-protocol attacks. TLS encrypts the contents of all transmission (except the handshake itself), making it difficult for attackers to control the data which could be used in a cross-protocol attack.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.4-Server-Push-Implicit-Headers\" /\u003e5.4 Server Push Implicit Headers\u003c/h2\u003e\u003cp\u003ePushed resources do not have an associated request. In order for existing HTTP cache control validations (such as the Vary header) to work, however, all cached resources must have a set of request headers. For this reason, browsers MUST be careful to inherit request headers from the associated stream for the push. This includes the 'Cookie' header.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.5-Use-of-Padding\" /\u003e5.5 Use of Padding\u003c/h2\u003e\u003cdiv\u003e\u003cdiv\u003ePadding within SPDY is not intended as a replacement for general purpose padding, such as might be provided by TLS. Redundant padding could even be counterproductive.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003ePadding can be used to hide the exact size of frame content. Padding is provided to mitigate specific attacks within HTTP. For example, attacks where compressed content includes both attacker-controlled plaintext and secret data (see for example, \u003ca href\u003d\"http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf\" rel\u003d\"nofollow\"\u003eBREACH\u003c/a\u003e).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eUse of padding can result in less protection than might seem immediately obvious. In particular, randomized amounts of padding only increase the number of frames that an attacker has to observe to recover the length. Padding to a constant size is preferable, since that reveals minimal size information. For attacks based on compression, disabling compression might be preferable to use of padding.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIntermediaries SHOULD NOT remove padding; though an intermediary could remove padding and add differing amounts if the intent is to improve the protections padding affords.\u003c/div\u003e\u003c/div\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-6.-Privacy-Considerations\" /\u003e6. Privacy Considerations\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-6.1-Long-Lived-Connections\" /\u003e6.1 Long Lived Connections\u003c/h2\u003e\u003cp\u003eSPDY aims to keep connections open longer between clients and servers in order to reduce the latency when a user makes a request. The maintenance of these connections over time could be used to expose private information. For example, a user using a browser hours after the previous user stopped using that browser may be able to learn about what the previous user was doing. This is a problem with HTTP in its current form as well, however the short lived connections make it less of a risk.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-6.2-SETTINGS-frame\" /\u003e6.2 SETTINGS frame\u003c/h2\u003e\u003cp\u003eThe SPDY SETTINGS frame allows servers to store out-of-band transmitted information about the communication between client and server on the client. Although this is intended only to be used to reduce latency, renegade servers could use it as a mechanism to store identifying information about the client in future requests.\u003c/p\u003e\u003cp\u003eClients implementing privacy modes, such as Google Chrome's \"incognito mode\", may wish to disable client-persisted SETTINGS storage.\u003c/p\u003e\u003cp\u003eClients MUST clear persisted SETTINGS information when clearing the cookies.\u003c/p\u003e\u003cp\u003eTODO: Put range maximums on each type of setting to limit inappropriate uses.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-7.-Incompatibilities-with-SPDY-draft-3\" /\u003e7. Incompatibilities with SPDY draft 3\u003c/h1\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eHere is a list of the major changes between draft 3.1 and draft 3.\u003c/p\u003e\u003cul style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cli\u003eRevision of flow control to include session-level flow control.\u003c/li\u003e\u003cli\u003eRemoval of CREDENTIAL frame and associated error codes.\u003c/li\u003e\u003cli\u003eGOAWAY clarified to ensure that SETTINGS and GOAWAY remain orthogonal.\u003c/li\u003e\u003c/ul\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003eHere is a list of the major changes between draft 3.2 and draft 3.1\u003c/font\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont face\u003d\"Times\" size\u003d\"3\"\u003eAdded DATA frame padding\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-8.-Requirements-Notation\" /\u003e8. Requirements Notation\u003c/h1\u003e\u003cp\u003eThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this document are to be interpreted as described in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2119\" rel\u003d\"nofollow\"\u003eRFC 2119\u003c/a\u003e.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-9.-Acknowledgements\" /\u003e9. Acknowledgements\u003c/h1\u003e\u003cp\u003eMany individuals have contributed to the design and evolution of SPDY: Adam Langley, Wan-Teh Chang, Jim Morrison, Mark Nottingham, Alyssa Wilk, Costin Manolache, William Chan, Vitaliy Lvin, Joe Chan, Adam Barth, Ryan Hamilton, Gavin Peters, Kent Alstad, Kevin Lindsay, Paul Amer, Fan Yang, Jonathan Leighton, Hasan Khalil, Ryan \u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-10.-Normative-References\" /\u003e10. Normative References\u003c/h1\u003e\u003ctable\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003cb\u003e[TLSNPN]\u003c/b\u003e\u003c/td\u003e\u003ctd\u003eLangley, A., “\u003ca href\u003d\"http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\" rel\u003d\"nofollow\"\u003eTLS Next Protocol Negotiation\u003c/a\u003e”, \u0026lt;\u003ca href\u003d\"http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\" rel\u003d\"nofollow\"\u003ehttp://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\u003c/a\u003e\u0026gt;.\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cb\u003e[ASCII]\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e“US-ASCII. Coded Character Set - 7-Bit American Standard Code for Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.”.\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cb\u003e[UDELCOMPRESSION]\u003c/b\u003e\u003c/td\u003e\u003ctd\u003eYang, F., Amer, P., and J. Leighton, “\u003ca href\u003d\"http://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\" rel\u003d\"nofollow\"\u003eA Methodology to Derive SPDY’s Initial Dictionary for Zlib Compression\u003c/a\u003e”, \u0026lt;\u003ca href\u003d\"http://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\" rel\u003d\"nofollow\"\u003ehttp://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\u003c/a\u003e\u0026gt;.\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-11.-Errata\" /\u003e11. Errata\u003c/h1\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eSection 2.6.6 originally listed INTERNAL_ERROR as status code 11.\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003chr /\u003e\u003cdiv\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Authors-Addresses\" /\u003eAuthors' Addresses\u003c/h1\u003e\u003caddress\u003eMike Belshe Twist EMail: \u003ca href\u003d\"mailto:mbelshe@chromium.org\"\u003embelshe@chromium.org\u003c/a\u003e\u003c/address\u003e\u003caddress\u003eRoberto Peon Google, Inc EMail: \u003ca href\u003d\"mailto:fenix@google.com\"\u003efenix@google.com\u003c/a\u003e\u003c/address\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/385872135698932510"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft3-2"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5825100101924839608"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4181298934531176809/13"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5825100101924839608"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5825100101924839608"}],"author":[{"name":{"$t":"William Chan"},"email":{"$t":"willchan@chromium.org"}}],"sites$pageName":{"$t":"spdy-protocol-draft3-2"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"WSl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8105047912391157367"},"published":{"$t":"2012-06-14T23:17:42.398Z"},"updated":{"$t":"2014-02-05T23:53:22.797Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-05T23:53:21.134Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Isolated Sites"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-NOTE:-This-project-is-no-longer-being-pursued-and-http:-crbug.com-69335-has-been-marked-WontFix.-We-are-investigating-other-ways-to-get-similar-protections-once-the-Site-Isolation-effort-is-deployed.\" /\u003e\u003cfont color\u003d\"#ff0000\"\u003eNOTE:\u003c/font\u003e \u003cspan style\u003d\"font-weight:normal\"\u003eThis project is no longer being pursued, and \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:normal\"\u003e\u003ca href\u003d\"http://crbug.com/69335\"\u003ehttp://crbug.com/69335\u003c/a\u003e has been marked WontFix.  We are investigating other ways to get similar protections once the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/site-isolation\"\u003eSite Isolation\u003c/a\u003e effort is deployed.\u003c/span\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h3\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Motivation\" /\u003eMotivation\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eFor browsing high value web sites (e.g., your bank account), Isolated Sites help provide stronger protection against cross-origin attacks, such as reflected XSS and CSRF.  See this paper for more details: \u003ca href\u003d\"http://www.charlesreis.com/research/publications/ccs-2011.pdf\" rel\u003d\"nofollow\"\u003eApp Isolation: Get the Security of Multiple Browsers with Just One\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-How-it-works\" /\u003e\u003cfont size\u003d\"3\"\u003eHow it works\u003c/font\u003e\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eA user designates a set of URLs to be be an \"isolated site.\"  This can be done either via an extension API or via chrome://settings/content (still to be flushed out).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen you perform a top-level navigation to an isolated site, it will behave as if you are visiting it from a separate browser. Any state that would be used for browsing (cookie store, cache, localstorage, etc.) will not be shared with your normal browsing session.  This includes any subresource loads, subframes, or javascript XHR calls.  A dedicated renderer processes are used as well, so that any in-memory state is also isolated from your normal browsing session. This helps shield the isolated app from most known cross-origin attacks, from reflected XSS to full WebKit exploits.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAs an example, suppose you have designated http://isolatedsite.com to be isolated and that http://isolatedsite.com serves the following HTML:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  \u0026lt;html\u0026gt;\u0026lt;body\u0026gt;\u0026lt;iframe src\u003d\"http://thirdparty.com\"\u0026gt;\u0026lt;/iframe\u0026gt;\u0026lt;/body\u0026gt;\u0026lt;/head\u0026gt;\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eDuring your browsing session, you directly visit http://thirdparty.com in a different tab and authenticate.  Now Chrome has cookies for thirdparty.com in your general browsing session.  However, within the isolated site, the http://thirdparty.com iframe on http://isolatedsite.com does not have access to those cookies, so you do not appear logged in.  The iframe is loaded in the context of the isolated site, so it behaves as if it is on a different browser than your first tab.  Conversely, any cookies set in the iframe inside the isolated site will remain attached only to the isolated site and not affect the state of the rest of the browser.\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Requirements\" /\u003eRequirements\u003c/h3\u003e\u003cdiv\u003eThe browser process must create a partitioned view of the data based on the site that is requesting the data.  This includes modifying at least the following objects to support partitioning the data:\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eCookies and Cache (via URLRequestContext)\u003c/li\u003e\u003cli\u003eHTML5 Storage (via DomStorage)\u003c/li\u003e\u003cli\u003eIndexDB (via IndexDBContext)\u003c/li\u003e\u003cli\u003eFilesystem access (via FileSystemContext)\u003c/li\u003e\u003cli\u003eAppCache access (via AppCacheService)\u003c/li\u003e\u003cli\u003eQuotaManager access (via QuotaManager)\u003c/li\u003e\u003cli\u003eDatabaseTracker access (via DataBaseTracker)\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003eFor now, we are aiming to partition this data on a per-process basis.  This may require Chrome to create a larger number of processes (rather than sharing processes when a limit is reached), but it is simpler than modifying WebKit to handle multiple storage contexts within a single renderer process.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Current-State\" /\u003eCurrent State\u003c/h3\u003e\u003c/div\u003e\u003cdiv\u003eTracking bug here: \u003ca href\u003d\"http://crbug.com/69335\"\u003ehttp://crbug.com/69335\u003c/a\u003e (marked WontFix)\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eMuch of the state isolation infrastructure needed for this effort now exists in the StoragePartition class, which is used by Chrome's Platform Apps.  Chrome no longer supports navigating from one StoragePartition to another, though, which would be necessary for this Isolated Sites proposal.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/isolated-sites"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8105047912391157367"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8105047912391157367"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8105047912391157367"}],"author":[{"name":{"$t":"Albert Wong"},"email":{"$t":"ajwong@chromium.org"}}],"sites$pageName":{"$t":"isolated-sites"},"sites$revision":{"$t":"10"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1553370065433002271"},"published":{"$t":"2013-05-02T20:22:51.905Z"},"updated":{"$t":"2014-02-02T07:13:04.895Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-02T07:13:04.895Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Benchmarks \u003d\u003d Measurements + Page Set"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003eOverview\u003c/h2\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eTelemetry is opinionated in what a benchmark is. A benchmark is: \u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eA PageMeasurement, which is a canned way to measure an arbitrary page. The measurement really should work for any page.\u003cbr /\u003eGood: Number of DOM Nodes in a Page\u003cbr /\u003eBad: Number of DOM Nodes in Gmail\u003cbr /\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eA page set, which is a list of pages your PM is interested in\u003cbr /\u003eGood: top 25 websites. The 10 most interesting ways users use our webapp\u003cbr /\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eBad: page set for measuring memory, another page set for measuring scrolling\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003eHere's why you care:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"line-height:20px;font-family:Roboto,arial,sans-serif;font-size:10pt\"\u003eWriting a good measurement is really hard, and Chrome has a bunch in tools/perf/ that are all-ready-to-go!\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Roboto, arial, sans-serif\"\u003e\u003cspan style\u003d\"line-height:20px\"\u003eOnce you can measure a page, you'll often want to track more pages just like that. And each page you try to add is going to have corner cases. And quirks. A request will come in for A/B tests. Pretty soon, you'll have your original measurement hacked up with tons of special cases to handle all your app's different use cases. This is cray!\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Roboto, arial, sans-serif\"\u003e\u003cspan style\u003d\"line-height:20px\"\u003eA page set is a product-level idea. PMs know what use cases are important for the product. Have them maintain the list of use cases as a page set.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"Roboto, arial, sans-serif\"\u003e\u003cspan style\u003d\"line-height:20px\"\u003eThe measurement is a code level idea. Given a given page, the measurement should evaluate how well you did. Engineers are good maintainers of a measurement class.\u003c/span\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch1 style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003ca name\u003d\"TOC-Check-out-tools-perf-page_sets-top_25-for-examples-of-page-sets.\" /\u003e\u003cspan style\u003d\"font-size:13.333333969116211px;font-weight:normal\"\u003eCheck out tools/perf/page_sets/top_25 for examples of page sets.\u003c/span\u003e\u003c/h1\u003e\u003ch1 style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003ca name\u003d\"TOC-An-Example\" /\u003e\u003cdiv style\u003d\"font-size:13.333333969116211px;font-weight:normal\"\u003e\u003ch2 style\u003d\"font-family:Arial,Verdana,sans-serif;line-height:normal\"\u003e\u003ca name\u003d\"TOC-An-Example1\" /\u003eAn Example\u003c/h2\u003e\u003c/div\u003e\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Lets-say-my-users-often-go-to-a-specific-page-click-a-button-and-scroll-a-div-that-shows-up.-I-could-measure-any-number-of-things:\" /\u003e\u003cspan style\u003d\"font-size:13.333333969116211px;font-weight:normal\"\u003eLets say my users often go to a specific page, click a button, and \u003cu\u003escroll\u003c/u\u003e a div that shows up. I could measure any number of things:\u003c/span\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eHow long it takes to go to that URL in a fresh tab until the div is up\u003c/li\u003e\u003cli\u003eHow smoothly I can scroll the div\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eHow much time I spend in key WebKit systems: javascript, style, layout, paint, compositing\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eHow much the memory footprint varies as I scroll the div\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eHow much time I spend decoding images, and painting the page\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003eThose are measurements. tools/perf has many measurements. \u003cb\u003eTHINK TWICE BEFORE YOU WRITE ANOTHER MEASUREMENT.\u003c/b\u003e There probably is one already.\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cb\u003eMost telemetry users should be putting their effort into writing page sets. \u003c/b\u003eIn this example, the page set isn't going to be \"the page set for measuring this specific url and how well it scrolls.\" Its going to be \"the page sets for my application,\" and since I have only one use case right now, it will be:\u003c/div\u003e\u003cblockquote style\u003d\"margin:0px 0px 0px 40px;border:none;padding:0px\"\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e{description: \"my teams pages that are worth benchmarking\",\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  pages: [\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  {\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"url\": \"my page's url\",\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"smoothness\": [\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e        {action: click_element, selector: \"#show-dialog\"},\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e        {action: scroll, selector: \"#dialog \u0026gt; #dialog-contents\"}\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      ]\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  }\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e}\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cbr /\u003eNow if I wanted to measure the smoothness of this use case:\u003cbr /\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e ./tools/perf/run_multipage_benchmark smoothness_benchmark my_team.json\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cbr /\u003eSuppose now you also want to test the perf of your main page without that dialog showing. Ugh, write another benchmark? Not so much... just add another page:\u003c/div\u003e\u003cblockquote style\u003d\"margin:0px 0px 0px 40px;border:none;padding:0px\"\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  {\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"url\": \"my page's url\",\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"smoothness\": [\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e        {action: scroll, selector: \"body\"}\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      ]\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  }\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cbr /\u003eAnd maybe I want to monitor memory for that page, by clicking a compose button 10 times. Again, thats not a benchmark, its just another entry in yoru page.\u003c/div\u003e\u003cblockquote style\u003d\"margin:0px 0px 0px 40px;border:none;padding:0px\"\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  {\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"url\": \"my page's url\",\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"smoothness\": [\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e        {action: scroll, selector: \"body\"}\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      ],\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      \"stress_memory\": [\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e        {action: repeat, times: 10,\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e         repeat: [\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e           {\"action\": click_element, selector: compose}, \u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e           {\"action\": \"click_element\", selector: \"#discard\"}\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e         ]\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e      ]\u003c/div\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e  }\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cspan style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003eVoila. Now we just: \u003c/span\u003e\u003cbr style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\" /\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv style\u003d\"font-family:Roboto,arial,sans-serif;font-size:13.333333969116211px;line-height:20px\"\u003e ./tools/perf/run_multipage_benchmark memory_benchmark my_team.json\u003c/div\u003e\u003c/blockquote\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/page-sets-and-benchmarks"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1553370065433002271"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1553370065433002271"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1553370065433002271"}],"author":[{"name":{"$t":"Nathaniel Duca"},"email":{"$t":"nduca@chromium.org"}}],"sites$pageName":{"$t":"page-sets-and-benchmarks"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1907003075064283735"},"published":{"$t":"2012-01-04T17:48:07.381Z"},"updated":{"$t":"2014-02-01T23:55:19.120Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-02-01T23:55:17.369Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Class Diagram: Blink core to Chrome Browser"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://docs.google.com/drawings/pub?id\u003d1BBnlbsJY8qjh5vVQmStZ5og1P3zbgAyCDnbyCq063FA\u0026amp;w\u003d1501\u0026amp;h\u003d908\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://docs.google.com/drawings/pub?id\u003d1BBnlbsJY8qjh5vVQmStZ5og1P3zbgAyCDnbyCq063FA\u0026amp;w\u003d1501\u0026amp;h\u003d908\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cfont size\u003d\"1\"\u003ehttps://docs.google.com/a/chromium.org/drawings/d/\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cfont size\u003d\"1\"\u003e[chromium.org or google.com accounts can edit the source google doc. Link split to suppress access request spam.]\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cfont size\u003d\"1\"\u003e1BBnlbsJY8qjh5vVQmStZ5og1P3zbgAyCDnbyCq063FA/edit \u003c/font\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/class-diagram-webkit-webcore-to-chrome-browser"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1907003075064283735"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1907003075064283735"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1907003075064283735"}],"author":[{"name":{"$t":"Vincent Scheib"},"email":{"$t":"scheib@chromium.org"}}],"sites$pageName":{"$t":"class-diagram-webkit-webcore-to-chrome-browser"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8744261881808231886"},"published":{"$t":"2012-03-15T20:58:11.167Z"},"updated":{"$t":"2014-01-29T23:04:17.959Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-01-29T23:04:16.595Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"HTTP Pipelining"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Objective\" /\u003eObjective\u003c/h2\u003e\u003cdiv\u003eSpeed up Chrome's network stack by enabling HTTP Pipelining. Pipelining issues multiple requests over a single connection without waiting for a response.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Risks\" /\u003eRisks\u003c/h2\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eBroken servers. Servers may ignore pipelined requests or corrupt the responses.\u003c/li\u003e\u003cli\u003eBroken proxies. May cause the same problems. Some users are behind \"transparent proxies,\" where the requests are proxied even though the user has not explicitly specified a proxy in their system configuration.\u003c/li\u003e\u003cli\u003eFront of queue blocking. The first request in a pipeline may block other requests in the pipeline. The net result of pipelining may be slower page loads.\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Mitigation\" /\u003eMitigation\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eResponse headers must have the following properties:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eHTTP/1.1\u003c/li\u003e\u003cli\u003eDeterminable content length, either through explicit Content-Length or chunked encoding\u003c/li\u003e\u003cli\u003eA keep-alive connection (implicit with HTTP/1.1)\u003c/li\u003e\u003cli\u003eNo authentication\u003c/li\u003e\u003c/ul\u003e\u003cdiv\u003ePipelining does not begin until these criteria have been met for an origin (host and port pair). If at any point one of these fail, the origin is black-listed in the client. If an origin has successfully pipelined before, it is remembered and pipelining begins immediately on next use.\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Status\" /\u003eStatus\u003c/h2\u003e\u003cdiv\u003eThe option to enable pipelining has been removed from Chrome, as there are known crashing bugs and known front-of-queue blocking issues. There are also a large number of servers and middleboxes that behave badly and inconsistently when pipelining is enabled. Until these are resolved, it's recommended nobody uses pipelining. Doing so currently requires a custom build of Chromium.\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2187609824886192973"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/network-stack/http-pipelining"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8744261881808231886"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8744261881808231886"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8744261881808231886"}],"author":[{"name":{"$t":"James Simonsen"},"email":{"$t":"simonjam@chromium.org"}}],"sites$pageName":{"$t":"http-pipelining"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7715566485741304833"},"published":{"$t":"2014-01-23T16:54:42.943Z"},"updated":{"$t":"2014-01-24T17:22:28.419Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-01-24T17:22:26.940Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Pwnium 4"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003ePwnium4@CanSecWest2014 \u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eChromium Security Reward Program\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eOfficial Rules\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eNO PURCHASE NECESSARY TO ENTER OR WIN. VOID WHERE PROHIBITED. CONTEST IS OPEN TO RESIDENTS OF THE 50 UNITED STATES, THE DISTRICT OF COLUMBIA AND WORLDWIDE, EXCEPT FOR RESIDENTS OF ITALY, BRAZIL, QUEBEC, CUBA, IRAN, SYRIA, NORTH KOREA, and SUDAN.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt;text-align:center\"\u003e\u003cspan style\u003d\"font-family:Arial;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eENTRY IN THIS CONTEST CONSTITUTES YOUR ACCEPTANCE OF THESE OFFICIAL RULES.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe Pwnium4@CanSecWest2014 Chromium Security Reward Program (\"Program\") is a skill contest designed to encourage involvement in improving the security of the Chromium project. Entrants submit original and unreported exploits relying on security bugs in Chrome OS including Chrome coupled with Flash / Chrome OS kernel and firmware / default apps on Chrome OS (an “Exploit”). The Exploits entrants develop will be evaluated by judges, who will award rewards to entrants who submit full and reliable Exploits (or Incomplete Exploits, as described below) with critical impact as determined in the sole discretion of the Judges.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003e1. BINDING AGREEMENT:\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e In order to enter the Program, you must agree to these Official Rules (“Rules”). Therefore, please read these Rules prior to entry to ensure you understand and agree. You agree that submission of an Exploit in the Program constitutes agreement to these Rules. You may not submit an Exploit to the Program and are not eligible to receive the rewards described in these Rules unless you agree to these Rules. These Rules form a binding legal agreement between you and Google with respect to the Program.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003e2. ELIGIBILITY:\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e To be eligible to enter the Program, you must be: (1) above the age of majority in the country, state, province or jurisdiction of residence (or at least twenty years old in Taiwan) at the time of entry; (2) \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003enot a resident of Italy, Brazil, Quebec, Cuba, Iran, Syria, North Korea, or Sudan\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e; (3) not a person or entity under U.S. export controls or sanctions; and (4) have access to the Internet as of January 23rd, 2014. Conte\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003est is void in Italy, Brazil, Quebec, Cuba, Iran, Syria, North Korea, Sudan), and where prohibited by law.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eEmployees, interns, contractors, and official office-holders of Google, and their parent companies, subsidiaries, affiliates, and their respective directors, officers, employees, advertising and promotion agencies, representatives, and agents (“Program Entities”), and members of the Program Entities’ and their immediate families (parents, siblings, children, spouses, and life partners of each, regardless of where they live) and members of the households (whether related or not) of such employees, officers and directors are ineligible to participate in the Program. Google reserves the right to verify eligibility and to adjudicate on any dispute at any time.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf you are entering as part of a company or on behalf of your employer, these rules are binding on you, individually, and/or your employer. If you are acting within the scope of your employment, as an employee, contractor, or agent of another party, you warrant that such party has full knowledge of your actions and has consented thereto, including your potential receipt of a reward. You further warrant that your actions do not violate your employer’s or company’s policies and procedures.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e3. \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSPONSOR:\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e The Program is sponsored by Google Inc. (“Google” or \"Sponsor\"), a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA, 94043, USA.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e4. PROGRAM PERIOD: The Program begins at 10:00:00 A.M. Pacific Time (PT) Zone (in Vancouver, Canada) at CanSecWest 2014 on March 12th, 2014 and ends at 12:00:00 P.M. PT on March 12th, 2014 (“Program Period”). Google may extend the Program Period in its sole discretion. ENTRANTS ARE RESPONSIBLE FOR DETERMINING THE CORRESPONDING TIME ZONE IN THEIR RESPECTIVE JURISDICTIONS.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e5. HOW TO ENTER: NO PURCHASE NECESSARY TO ENTER OR WIN. To enter the Program, register before 5:00:00 P.M. PST (Pacific Standard Time) on Monday, March 10th, 2014 by sending an email with your name to \u003c/span\u003e\u003ca href\u003d\"mailto:pwnium4@chromium.org\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003epwnium4@chromium.org\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e, and then visit the Google desk at CanSecWest 2014 in Vancouver, Canada during the Program Period. Entrants will be assigned a specific timeslot on March 12th, 2014 during which they may demonstrate Exploits to the Judges. Exploits must be demonstrated during entrant’s assigned time to be eligible for a reward, and must meet the “Exploit Requirements,” described below.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eEntrants are entirely responsible for all costs and fees associated with entrant’s participation in the Program and attending the CanSecWest 2014, including (but not limited to) admission fees, transportation, accommodation and living costs. All entries must be received before the end of the Program Period. Entries are void if they are in whole or part illegible, incomplete, damaged, altered, counterfeit, obtained through fraud, or late. All entries will be deemed made by the authorized account holder of the email address submitted at the time of submission, and potential reward recipients may be required to show proof of being the authorized account holder for that email address. The \"authorized account holder\" is the natural person assigned to an email address by an Internet service provider, online service provider, or other organization responsible for assigning email address for the domain.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eEXPLOIT REQUIREMENTS: The Exploit must meet the following criteria:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be an unreported and original exploit, which has not been shared or partially shared with anyone else or submitted in any other contests.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be an exploit relying on an unreported and original bug, bugs or security feature in Chrome OS, Flash or other software e.g. drivers.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be an attack that’s demonstrated against a base (WiFi) model of the ARM-based HP Chromebook 11, running the latest stable version of Chrome OS; or a 2GB WiFi model of the Acer C720 Intel Chromebook, running the latest stable version of Chrome OS.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be a remote exploit accessible through the Chrome browser, which works and is reliable.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be served from a password-authenticated and HTTPS-supported Google property, such as Google App Engine.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be present in the most recent supported channel(s) of Chrome OS.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be a critical vulnerability of high impact.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be authored or created by You.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e• Be submitted with corresponding documentation that details each bug exploited.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDuring the Program Period, Google, its agents, and/or the Judges (defined below) will be evaluating each Exploit to ensure that it meets the Exploit Requirements. Google reserves the right, in its sole discretion, to disqualify any entrant who submits an Exploit that does not meet the Exploit Requirements.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e6. JUDGING: Each Exploit submission will be judged by a panel of experts who are employees of Google (“Judges”). Each Exploit will be evaluated by the Judges as to whether the Exploit is a critical importance vulnerability of high impact, based on the potential for persistent access to the user’s account or guest mode on the Chrome operating system.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eJudges will evaluate each Exploit based upon the above criteria to determine whether it is critical impact and qualifies for a reward.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf a potential reward recipient is disqualified for any reason, the reward allocated to that recipient will be returned to the total reward pool. On or about March 17th, 2014, the potential reward recipients will be selected and notified by telephone and/or email, at Sponsor’s discretion. If a potential reward recipient does not respond to the notification attempt within five days from the first notification attempt, then such potential reward recipient may be disqualified and the allocated reward will be returned to the total reward pool. With respect to notification by telephone, such notification will be deemed given when the potential reward recipient engages in a live conversation with Sponsor or when a message is left on the potential reward recipient’s voicemail service or answering machine by the Sponsor, whichever occurs first. Except where prohibited by law, each potential reward recipient may be required to sign and return a Declaration of Eligibility and Liability and Publicity Release and provide any additional information that may be required by Sponsor. If required, potential reward recipients must return all such required documents within seven days following attempted notification or such potential reward recipient may be deemed to have forfeited the reward and the reward may be returned to the total reward pool. All notification requirements, as well as other requirements within these Rules, will be strictly enforced. In the event no Exploits are received, no rewards will be awarded. Determinations of judges are final and binding.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e7. REWARDS: Rewards for eligible Exploits will be allocated to eligible entrants on a first-come-first-served basis, based on time of submission during the Program Period specified above, until such time as the total reward pool of $2.71828 million USD is exhausted:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAn entrant submitting an Exploit demonstrating a Chrome OS system-level compromise delivered via a web page and triggerable when browsing in Guest mode and affecting all subsequent Guest mode sessions across reboots (“persistent Guest-to-Guest exploit”) using bugs in Chrome OS, as determined in the sole discretion of the Judges, will receive a reward of $150,000 USD (one hundred and fifty thousand U.S. dollars).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAn entrant submitting an Exploit demonstrating a Chrome browser-level compromise delivered via a web page using bugs in Chrome OS as determined in the sole discretion of the Judges, will receive a reward of $110,000 USD (one hundred and ten thousand U.S. dollars).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eGoogle reserves the right to issue partial rewards, in its sole discretion, for partial, incomplete or unreliable Exploits. Google may also consider issuing significant bonuses for any Entrant who demonstrates a particularly impressive or surprising exploit.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eEach reward recipient will also receive a Chromebook, provided such reward recipient resides in a country where Chromebooks are legally available.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eOdds of winning any reward depends on the number of eligible entries received during the Program Period and the skill of the entrants. \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe rewards will be awarded within approximately two weeks of receipt by Sponsor of final reward acceptance documents. No transfer, substitution or cash equivalent for rewards is allowed, except at Sponsor’s sole discretion. Sponsor reserves the right to substitute a reward, in whole or in part, of equal or greater monetary value if a reward cannot be awarded, in whole or in part, as described for any reason. Value is subject to market conditions, which can fluctuate and any difference between actual market value and ARV will not be awarded. The reward(s) may be subject to restrictions and/or licenses and may require additional hardware, software, service, or maintenance to use. The reward recipient shall bear all responsibility for use of the rewards(s) in compliance with any conditions imposed by such manufacturer(s), and any additional costs associated with its use, service, or maintenance. Program Entities have not made and Program Entities are not responsible in any manner for any warranties, representations, or guarantees, express or implied, in fact or law, relating to the reward(s), regarding the use, value or enjoyment of the reward(s), including, without limitation, its quality, mechanical condition, merchantability, or fitness for a particular purpose, with the exception of any standard manufacturer's warranty that may apply to the reward or any components thereto.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e9. TAXES: PAYMENTS TO POTENTIAL REWARD RECIPIENTS ARE SUBJECT TO THE EXPRESS REQUIREMENT THAT THEY SUBMIT TO GOOGLE ALL DOCUMENTATION REQUESTED BY GOOGLE TO PERMIT IT TO COMPLY WITH ALL APPLICABLE STATE, FEDERAL, LOCAL, AND FOREIGN (INCLUDING PROVINCIAL) TAX REPORTING AND WITHHOLDING REQUIREMENTS. ALL REWARDS WILL BE NET OF ANY TAXES GOOGLE IS REQUIRED BY LAW TO WITHHOLD. ALL TAXES IMPOSED ON REWARDS ARE THE SOLE RESPONSIBILITY OF THE REWARD RECIPIENTS. In order to receive a reward, potential reward recipients must submit the tax documentation requested by Google or otherwise required by applicable law, to Google or the relevant tax authority, all as determined by applicable law, including, where relevant, the law of the potential recipient’s country of residence. The potential reward recipients are responsible for ensuring that (s)he complies with all the applicable tax laws and filing requirements. If a potential reward recipient fails to provide such documentation or comply with such laws, the reward may be forfeited and Google may, in its sole discretion, return the reward to the total reward pool.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e10. GENERAL CONDITIONS: All federal, state, provincial and local laws and regulations apply. Google reserves the right to disqualify any entrant from the Program if, in Google’s sole discretion, it reasonably believes that the entrant has attempted to undermine the legitimate operation of the Program by cheating, deception, or other unfair playing practices or annoys, abuses, threatens or harasses any other entrants, Google, or the Judges.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e11. INTELLECTUAL PROPERTY RIGHTS: As between Google and the entrant, the entrant retains ownership of all intellectual and industrial property rights (including moral rights) in and to the Exploit. By submitting an Exploit to the Program, the entrant warrants and represents that he or she owns all of the intellectual and industrial property rights in and to the Exploit. As a condition of submission, entrant grants Google, its subsidiaries, agents and partner companies, a perpetual, irrevocable, worldwide, royalty-free, and non-exclusive license to use, reproduce, adapt, modify, publish, distribute, publicly perform, create a derivative work from, and publicly display the Exploit (1) for the purposes of allowing Google and the Judges to evaluate the Exploit for purposes of the Program, (2) for the purposes of evaluating the Exploit and improving Google and third party products, services, systems and networks and (3) in connection with advertising and promotion via communication to the public or other groups, including, but not limited to, the right to make screenshots, animations and Exploit clips available for promotional purposes.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e12. PRIVACY: \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eEntrant acknowledges and agrees that Google may collect, store, share and otherwise use personally identifiable information provided during the registration process and the Program, including, but not limited to, name, mailing address, phone number, and email address. Google will use this information in accordance with its Privacy Policy (\u003c/span\u003e\u003ca href\u003d\"http://www.google.com/policies/privacy/\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003ehttp://www.google.com/policies/privacy/\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003e), including for administering the Program and verifying Participant’s identity, postal address and telephone number in the event an entry qualifies for a reward.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.2499999523162841;margin-top:0pt;margin-bottom:12pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eParticipant’s information may also be transferred to countries outside the country of participant's residence, including the United States. Such other countries may not have privacy laws and regulations similar to those of the country of participant's residence.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.2499999523162841;margin-top:0pt;margin-bottom:12pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eIf a participant does not provide the mandatory data required at registration, Google reserves the right to disqualify the entry.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.2499999523162841;margin-top:0pt;margin-bottom:12pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eParticipant has the right to request access, review, rectification or deletion of any personal data held by Google in connection with the Contest by writing to Google at this email address: security@chromium.org.\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e13. PUBLICITY: By accepting a reward, entrant agrees to Sponsor and its agencies use of his or her name and/or likeness and Exploit for advertising and promotional purposes without additional compensation, unless prohibited by law.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e14. WARRANTY AND INDEMNITY: Entrants warrant that their Exploits are their own original work and, as such, they are the sole and exclusive owner and rights holder of the submitted Exploit and that they have the right to submit the Exploit in the Program and grant all required licenses. Each entrant agrees not to submit any Exploit that (1) infringes any third party proprietary rights, intellectual property rights, industrial property rights, personal or moral rights or any other rights, including without limitation, copyright, trademark, patent, trade secret, privacy, publicity or confidentiality obligations; or (2) otherwise violates the applicable state, federal, provincial or local law.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTo the maximum extent permitted by law, each entrant indemnifies and agrees to keep indemnified Sponsor at all times from and against any liability, claims, demands, losses, damages, costs and expenses resulting from any act, default or omission of the entrant and/or a breach of any warranty set forth herein. To the maximum extent permitted by law, each entrant agrees to defend, indemnify and hold harmless the Sponsor from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) any Esploit or other material uploaded or otherwise provided by the entrant that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, (b) any misrepresentation made by the entrant in connection with the Program; (c) any non-compliance by the entrant with these Rules; (d) claims brought by persons or entities other than the parties to these Rules arising from or related to the entrant’s involvement with the Program; (e) acceptance, possession, misuse or use of any prize, or participation in any Program-related activity or participation in this Program; (f) any malfunction or other problem with the Program site; (g) any error in the collection, processing, or retention of submission information; or (h) any typographical or other error in the printing, offering or announcement of any reward or reward recipients.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e15. ELIMINATION: Any false information provided within the context of the Program by any entrant concerning identity, mailing address, telephone number, email address, ownership of right or non-compliance with these Rules or the like may result in the immediate elimination of the entrant from the Program.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e16. INTERNET: Sponsor is not responsible for any malfunction of the entire Program site or any late, lost, damaged, misdirected, incomplete, illegible, undeliverable, or destroyed Exploits or entry materials due to system errors, failed, incomplete or garbled computer or other telecommunication transmission malfunctions, hardware or software failures of any kind, lost or unavailable network connections, typographical or system/human errors and failures, technical malfunction(s) of any telephone network or lines, cable connections, satellite transmissions, servers or providers, or computer equipment, traffic congestion on the Internet or at the Program site, or any combination thereof, including other telecommunication, cable, digital or satellite malfunctions which may limit a participant’s ability to participate.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e17. RIGHT TO CANCEL, MODIFY OR DISQUALIFY: If for any reason the Program is not capable of running as planned, including infection by computer virus, bugs, tampering, unauthorized intervention, fraud, technical failures, or any other causes which corrupt or affect the administration, security, fairness, integrity, or proper conduct of the Program, Google reserves the right at its sole discretion to cancel, terminate, modify or suspend the Program. Google further reserves the right to disqualify any entrant who tampers with the submission process or any other part of the Program or Program site. Any attempt by an entrant to deliberately damage any web site, including the Program site, or undermine the legitimate operation of the Program is a violation of criminal and civil laws and should such an attempt be made, Google reserves the right to seek damages from any such entrant to the fullest extent of the applicable law.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e18. NOT AN OFFER OR CONTRACT OF EMPLOYMENT: Under no circumstances shall the submission of a Exploit into the Program, the awarding of a reward, or anything in these Rules be construed as an offer or contract of employment with either Google, or any other Program entities. You acknowledge that you have submitted your Exploit voluntarily and not in confidence or in trust. You acknowledge that no confidential, fiduciary, agency or other relationship or implied-in-fact contract now exists between you and Google or any other Program entities and that no such relationship is established by your submission of an Exploit under these Rules.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e19. FORUM AND RECOURSE TO JUDICIAL PROCEDURES: These Rules shall be governed by, subject to, and construed in accordance with the laws of the State of California, United States of America, excluding all conflict of law rules. If any provision(s) of these Rules are held to be invalid or unenforceable, all remaining provisions hereof will remain in full force and effect. To the extent permitted by law, the rights to litigate, seek injunctive relief or make any other recourse to judicial or any other procedure in case of disputes or claims resulting from or in connection with this Program are hereby excluded, and all participants expressly waive any and all such rights.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e20. ARBITRATION: By entering the Program, you agree that exclusive jurisdiction for any dispute, claim, or demand related in any way to the Program will be decided by binding arbitration. All disputes between you and Google of whatsoever kind or nature arising out of these Rules, shall be submitted to Judicial Arbitration and Mediation Services, Inc. (“JAMS”) for binding arbitration under its rules then in effect in the San Jose, California, USA area, before one arbitrator to be mutually agreed upon by both parties. The parties agree to share equally in the arbitration costs incurred.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e20. REWARD RECIPIENT’S LIST: Reward recipients will be posted on the Program site for six months following the conclusion of the Program.\u003c/span\u003e\u003c/p\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6743906577140407009"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/pwnium-4"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7715566485741304833"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7715566485741304833"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7715566485741304833"}],"author":[{"name":{"$t":"Jorge Lucangeli Obes"},"email":{"$t":"jorgelo@chromium.org"}}],"sites$pageName":{"$t":"pwnium-4"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7422579101903673167"},"published":{"$t":"2013-03-09T00:25:42.482Z"},"updated":{"$t":"2014-01-22T21:14:38.898Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-01-22T21:14:37.123Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Chromium OS Architecture Porting Guide"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Various-Upstream-Projects\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eVarious Upstream Projects\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Existing-Gentoo-Support\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003eExisting Gentoo Support\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chromium-OS-Pieces\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eChromium OS Pieces\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eSo you decided that the existing cpu architectures (Intel's x86_64/i686 and ARM's 32-bit arm) platforms weren't up to the task for your next system?  Instead, you opted for some magical and new architecture?  What you desire is possible, but you should buckle up and prepare for a bumpy ride!\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Various-Upstream-Projects\" /\u003eVarious Upstream Projects\u003c/h2\u003e\r\n\u003cp\u003eKeep in mind that Chromium OS is based on a lot of upstream projects that we have not authored.  That means you can't really get by with just porting Chromium OS and forgetting about the rest.\u003c/p\u003e\r\n\u003cp\u003eFor example, your architecture must already be supported by (at least):\u003c/p\u003e\r\n\r\n\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"http://sourceware.org/binutils/\" rel\u003d\"nofollow\"\u003eBinutils\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://gcc.gnu.org/\" rel\u003d\"nofollow\"\u003eGCC\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://sourceware.org/gdb/\" rel\u003d\"nofollow\"\u003eGDB\u003c/a\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://sourceware.org/glibc/\" rel\u003d\"nofollow\"\u003eGlibc\u003c/a\u003e (sorry, but alternative C libraries are not currently supported e.g. \u003ca href\u003d\"http://www.uclibc.org/\" rel\u003d\"nofollow\"\u003euClibc\u003c/a\u003e)\u003c/li\u003e\r\n\u003cli\u003e\u003ca href\u003d\"http://kernel.org/\" rel\u003d\"nofollow\"\u003eLinux kernel\u003c/a\u003e\u003c/li\u003e\r\n\u003cul\u003e\u003cli\u003eMust have \u003ca href\u003d\"http://en.wikipedia.org/wiki/Memory_management_unit\" rel\u003d\"nofollow\"\u003eCONFIG_MMU\u003dy\u003c/a\u003e (if you don't know what this means, then you most likely have one, and can thus disregard)\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\r\nThis is just the tip of the iceberg.  If you're missing any of these pieces, then you've got a lot of work ahead of you.  Come visit us once you've gotten those sorted out.\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Existing-Gentoo-Support\" /\u003eExisting Gentoo Support\u003c/h3\u003e\r\n\u003cp\u003eChromium OS is based on \u003ca href\u003d\"http://www.gentoo.org/\" rel\u003d\"nofollow\"\u003eGentoo\u003c/a\u003e.  \u003cfont size\u003d\"2\"\u003eHopefully you've selected a processor that they already support (they support many already).  You can find the current list here:\u003c/font\u003e\u003cbr /\u003e\r\n   \u003ca href\u003d\"http://sources.gentoo.org/profiles/arch.list\" rel\u003d\"nofollow\"\u003ehttp://sources.gentoo.org/profiles/arch.list\u003c/a\u003e\u003c/p\u003e\r\n\u003cp\u003eFind what you're looking for?  Great!  Life will be much easier and you should move on to the next section.\u003c/p\u003e\r\n\u003cp\u003eYour architecture not listed there?  Sorry!  You're first going to have to coordinate with the \u003ca href\u003d\"http://www.gentoo.org/main/en/lists.xml\" rel\u003d\"nofollow\"\u003eGentoo maintainers\u003c/a\u003e in porting to your crazy architecture.  \u003cspan style\u003d\"font-size:10pt\"\u003eCome visit us once you've gotten those sorted out.\u003c/span\u003e\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Chromium-OS-Pieces\" /\u003eChromium OS Pieces\u003c/h2\u003e\r\n\u003cp\u003eMore To Come!\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8281191106998714061"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/how-tos-and-troubleshooting/chromiumos-architecture-porting-guide"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7422579101903673167"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7422579101903673167"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7422579101903673167"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"chromiumos-architecture-porting-guide"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"Wil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4181298934531176809"},"published":{"$t":"2013-09-26T20:33:58.812Z"},"updated":{"$t":"2014-01-15T20:05:49.165Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-01-15T20:05:47.719Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"SPDY Protocol - Draft 3.1"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003e1. Overview\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.1-Document-Organization\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003e1.1 Document Organization\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.2-Definitions\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003e1.2 Definitions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.-SPDY-Framing-Layer\"\u003e\u003cstrong\u003e2 \u003c/strong\u003e2. SPDY Framing Layer\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.1-Session-Connections-\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003e2.1 Session (Connections)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2-Framing\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003e2.2 Framing\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2.1-Control-frames\"\u003e\u003cstrong\u003e2.2.1 \u003c/strong\u003e2.2.1 Control frames\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2.2-Data-frames\"\u003e\u003cstrong\u003e2.2.2 \u003c/strong\u003e2.2.2 Data frames\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3-Streams\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003e2.3 Streams\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.1-Stream-frames\"\u003e\u003cstrong\u003e2.3.1 \u003c/strong\u003e2.3.1 Stream frames\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2-Stream-creation\"\u003e\u003cstrong\u003e2.3.2 \u003c/strong\u003e2.3.2 Stream creation\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2.1-Unidirectional-streams\"\u003e\u003cstrong\u003e2.3.2.1 \u003c/strong\u003e2.3.2.1 Unidirectional streams\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2.2-Bidirectional-streams\"\u003e\u003cstrong\u003e2.3.2.2 \u003c/strong\u003e2.3.2.2 Bidirectional streams\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.3-Stream-priority\"\u003e\u003cstrong\u003e2.3.3 \u003c/strong\u003e2.3.3 Stream priority\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.4-Stream-headers\"\u003e\u003cstrong\u003e2.3.4 \u003c/strong\u003e2.3.4 Stream headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.5-Stream-data-exchange\"\u003e\u003cstrong\u003e2.3.5 \u003c/strong\u003e2.3.5 Stream data exchange\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.6-Stream-half-close\"\u003e\u003cstrong\u003e2.3.6 \u003c/strong\u003e2.3.6 Stream half-close\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.7-Stream-close\"\u003e\u003cstrong\u003e2.3.7 \u003c/strong\u003e2.3.7 Stream close\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4-Error-Handling\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003e2.4 Error Handling\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4.1-Session-Error-Handling\"\u003e\u003cstrong\u003e2.4.1 \u003c/strong\u003e2.4.1 Session Error Handling\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4.2-Stream-Error-Handling\"\u003e\u003cstrong\u003e2.4.2 \u003c/strong\u003e2.4.2 Stream Error Handling\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.5-Data-flow\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003e2.5 Data flow\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6-Control-frame-types\"\u003e\u003cstrong\u003e2.6 \u003c/strong\u003e2.6 Control frame types\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.1-SYN_STREAM\"\u003e\u003cstrong\u003e2.6.1 \u003c/strong\u003e2.6.1 SYN_STREAM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.2-SYN_REPLY\"\u003e\u003cstrong\u003e2.6.2 \u003c/strong\u003e2.6.2 SYN_REPLY\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.3-RST_STREAM\"\u003e\u003cstrong\u003e2.6.3 \u003c/strong\u003e2.6.3 RST_STREAM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.4-SETTINGS\"\u003e\u003cstrong\u003e2.6.4 \u003c/strong\u003e2.6.4 SETTINGS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.5-PING\"\u003e\u003cstrong\u003e2.6.5 \u003c/strong\u003e2.6.5 PING\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.6-GOAWAY\"\u003e\u003cstrong\u003e2.6.6 \u003c/strong\u003e2.6.6 GOAWAY\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.7-HEADERS\"\u003e\u003cstrong\u003e2.6.7 \u003c/strong\u003e2.6.7 HEADERS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.8-WINDOW_UPDATE\"\u003e\u003cstrong\u003e2.6.8 \u003c/strong\u003e2.6.8 WINDOW_UPDATE\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-The-Flow-Control-Window\"\u003e\u003cstrong\u003e2.6.8.1 \u003c/strong\u003eThe Flow Control Window\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Initial-Flow-Control-Window-Size\"\u003e\u003cstrong\u003e2.6.8.2 \u003c/strong\u003eInitial Flow Control Window Size\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Reducing-the-Stream-Window-Size\"\u003e\u003cstrong\u003e2.6.8.3 \u003c/strong\u003eReducing the Stream Window Size\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.9-CREDENTIAL\"\u003e\u003cstrong\u003e2.6.9 \u003c/strong\u003e2.6.9 CREDENTIAL\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.10-Name-Value-Header-Block\"\u003e\u003cstrong\u003e2.6.10 \u003c/strong\u003e2.6.10 Name/Value Header Block\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.10.1-Compression\"\u003e\u003cstrong\u003e2.6.10.1 \u003c/strong\u003e2.6.10.1 Compression\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.-HTTP-Layering-over-SPDY\"\u003e\u003cstrong\u003e3 \u003c/strong\u003e3. HTTP Layering over SPDY\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.1-Connection-Management\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003e3.1 Connection Management\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.1.1-Use-of-GOAWAY\"\u003e\u003cstrong\u003e3.1.1 \u003c/strong\u003e3.1.1 Use of GOAWAY\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2-HTTP-Request-Response\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003e3.2 HTTP Request/Response\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.1-Request\"\u003e\u003cstrong\u003e3.2.1 \u003c/strong\u003e3.2.1 Request\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.2-Response\"\u003e\u003cstrong\u003e3.2.2 \u003c/strong\u003e3.2.2 Response\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3-Authentication\"\u003e\u003cstrong\u003e3.2.3 \u003c/strong\u003e3.2.3 Authentication\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3.1-Stateless-Authentication\"\u003e\u003cstrong\u003e3.2.3.1 \u003c/strong\u003e3.2.3.1 Stateless Authentication\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3.2-Stateful-Authentication\"\u003e\u003cstrong\u003e3.2.3.2 \u003c/strong\u003e3.2.3.2 Stateful Authentication\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3-Server-Push-Transactions\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003e3.3 Server Push Transactions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3.1-Server-implementation\"\u003e\u003cstrong\u003e3.3.1 \u003c/strong\u003e3.3.1 Server implementation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3.2-Client-implementation\"\u003e\u003cstrong\u003e3.3.2 \u003c/strong\u003e3.3.2 Client implementation\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.-Design-Rationale-and-Notes\"\u003e\u003cstrong\u003e4 \u003c/strong\u003e4. Design Rationale and Notes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.1-Separation-of-Framing-Layer-and-Application-Layer\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003e4.1 Separation of Framing Layer and Application Layer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.2-Error-handling---Framing-Layer\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003e4.2 Error handling - Framing Layer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.3-One-Connection-Per-Domain\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003e4.3 One Connection Per Domain\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.4-Fixed-vs-Variable-Length-Fields\"\u003e\u003cstrong\u003e4.4 \u003c/strong\u003e4.4 Fixed vs Variable Length Fields\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.5-Compression-Context-s-\"\u003e\u003cstrong\u003e4.5 \u003c/strong\u003e4.5 Compression Context(s)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.6-Unidirectional-streams\"\u003e\u003cstrong\u003e4.6 \u003c/strong\u003e4.6 Unidirectional streams\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.7-Data-Compression\"\u003e\u003cstrong\u003e4.7 \u003c/strong\u003e4.7 Data Compression\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.8-Server-Push\"\u003e\u003cstrong\u003e4.8 \u003c/strong\u003e4.8 Server Push\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.-Security-Considerations\"\u003e\u003cstrong\u003e5 \u003c/strong\u003e5. Security Considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.1-Use-of-Same-origin-constraints\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003e5.1 Use of Same-origin constraints\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.2-HTTP-Headers-and-SPDY-Headers\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003e5.2 HTTP Headers and SPDY Headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.3-Cross-Protocol-Attacks\"\u003e\u003cstrong\u003e5.3 \u003c/strong\u003e5.3 Cross-Protocol Attacks\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.4-Server-Push-Implicit-Headers\"\u003e\u003cstrong\u003e5.4 \u003c/strong\u003e5.4 Server Push Implicit Headers\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.-Privacy-Considerations\"\u003e\u003cstrong\u003e6 \u003c/strong\u003e6. Privacy Considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.1-Long-Lived-Connections\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003e6.1 Long Lived Connections\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.2-SETTINGS-frame\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003e6.2 SETTINGS frame\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-7.-Incompatibilities-with-SPDY-draft-3\"\u003e\u003cstrong\u003e7 \u003c/strong\u003e7. Incompatibilities with SPDY draft #3\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-8.-Requirements-Notation\"\u003e\u003cstrong\u003e8 \u003c/strong\u003e8. Requirements Notation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-9.-Acknowledgements\"\u003e\u003cstrong\u003e9 \u003c/strong\u003e9. Acknowledgements\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-10.-Normative-References\"\u003e\u003cstrong\u003e10 \u003c/strong\u003e10. Normative References\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-11.-Errata\"\u003e\u003cstrong\u003e11 \u003c/strong\u003e11. Errata\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Authors-Addresses\"\u003e\u003cstrong\u003e12 \u003c/strong\u003eAuthors' Addresses\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-1.-Overview\" /\u003e1. Overview\u003c/h1\u003e\u003cp\u003eOne of the bottlenecks of HTTP implementations is that HTTP relies on multiple connections for concurrency. This causes several problems, including additional round trips for connection setup, slow-start delays, and connection rationing by the client, where it tries to avoid opening too many connections to any single server. HTTP pipelining helps some, but only achieves partial multiplexing. In addition, pipelining has proven non-deployable in existing browsers due to intermediary interference.\u003c/p\u003e\u003cp\u003eSPDY adds a framing layer for multiplexing multiple, concurrent streams across a single TCP connection (or any reliable transport stream). The framing layer is optimized for HTTP-like request-response streams, such that applications which run over HTTP today can work over SPDY with little or no change on behalf of the web application writer.\u003c/p\u003e\u003cp\u003eThe SPDY session offers four improvements over HTTP:\u003c/p\u003e\u003cul\u003e\u003cli\u003eMultiplexed requests: There is no limit to the number of requests that can be issued concurrently over a single SPDY connection.\u003c/li\u003e\u003cli\u003ePrioritized requests: Clients can request certain resources to be delivered first. This avoids the problem of congesting the network channel with non-critical resources when a high-priority request is pending.\u003c/li\u003e\u003cli\u003eCompressed headers: Clients today send a significant amount of redundant data in the form of HTTP headers. Because a single web page may require 50 or 100 subrequests, this data is significant.\u003c/li\u003e\u003cli\u003eServer pushed streams: Server Push enables content to be pushed from servers to clients without a request.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eSPDY attempts to preserve the existing semantics of HTTP. All features such as cookies, ETags, Vary headers, Content-Encoding negotiations, etc work as they do with HTTP; SPDY only replaces the way the data is written to the network.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1.1-Document-Organization\" /\u003e1.1 Document Organization\u003c/h2\u003e\u003cp\u003eThe SPDY Specification is split into two parts: a framing layer (Section 2), which multiplexes a TCP connection into independent, length-prefixed frames, and an HTTP layer (Section 3), which specifies the mechanism for overlaying HTTP request/response pairs on top of the framing layer. While some of the framing layer concepts are isolated from the HTTP layer, building a generic framing layer has not been a goal. The framing layer is tailored to the needs of the HTTP protocol and server push.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1.2-Definitions\" /\u003e1.2 Definitions\u003c/h2\u003e\u003cul\u003e\u003cli\u003eclient: The endpoint initiating the SPDY session.\u003c/li\u003e\u003cli\u003econnection: A transport-level connection between two endpoints.\u003c/li\u003e\u003cli\u003eendpoint: Either the client or server of a connection.\u003c/li\u003e\u003cli\u003eframe: A header-prefixed sequence of bytes sent over a SPDY session.\u003c/li\u003e\u003cli\u003eserver: The endpoint which did not initiate the SPDY session.\u003c/li\u003e\u003cli\u003esession: A synonym for a connection.\u003c/li\u003e\u003cli\u003esession error: An error on the SPDY session.\u003c/li\u003e\u003cli\u003estream: A bi-directional flow of bytes across a virtual channel within a SPDY session.\u003c/li\u003e\u003cli\u003estream error: An error on an individual SPDY stream.\u003c/li\u003e\u003c/ul\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-2.-SPDY-Framing-Layer\" /\u003e2. SPDY Framing Layer\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.1-Session-Connections-\" /\u003e2.1 Session (Connections)\u003c/h2\u003e\u003cp\u003eThe SPDY framing layer (or \"session\") runs atop a reliable transport layer such as TCP. The client is the TCP connection initiator. SPDY connections are persistent connections.\u003c/p\u003e\u003cp\u003eFor best performance, it is expected that clients will not close open connections until the user navigates away from all web pages referencing a connection, or until the server closes the connection. Servers are encouraged to leave connections open for as long as possible, but can terminate idle connections if necessary. When either endpoint closes the transport-level connection, it MUST first send a GOAWAY (Section 2.6.6) frame so that the endpoints can reliably determine if requests finished before the close.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.2-Framing\" /\u003e2.2 Framing\u003c/h2\u003e\u003cp\u003eOnce the connection is established, clients and servers exchange framed messages. There are two types of frames: control frames (Section 2.2.1) and data frames (Section 2.2.2). Frames always have a common header which is 8 bytes in length.\u003c/p\u003e\u003cp\u003eThe first bit is a control bit indicating whether a frame is a control frame or data frame. Control frames carry a version number, a frame type, flags, and a length. Data frames contain the stream ID, flags, and the length for the payload carried after the common header. The simple header is designed to make reading and writing of frames easy.\u003c/p\u003e\u003cp\u003eAll integer values, including length, version, and type, are in network byte order. SPDY does not enforce alignment of types in dynamically sized frames.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.2.1-Control-frames\" /\u003e2.2.1 Control frames\u003c/h3\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|C| Version(15bits) | Type(16bits) |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Data |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The 'C' bit is a single bit indicating if this is a control message. For control frames this value is always 1.\u003c/p\u003e\u003cp\u003eVersion: The version number of the SPDY protocol. This document describes SPDY version 3.1, which is represented as version 3.\u003c/p\u003e\u003cp\u003eType: The type of control frame. See Control Frames (Section 2.6) for the complete list of control frames.\u003c/p\u003e\u003cp\u003eFlags: Flags related to this frame. Flags for control frames and data frames are different.\u003c/p\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field.\u003c/p\u003e\u003cp\u003eData: data associated with this control frame. The format and length of this data is controlled by the control frame type.\u003c/p\u003e\u003cp\u003eControl frame processing requirements:\u003c/p\u003e\u003cul\u003e\u003cli\u003eNote that full length control frames (16MB) can be large for implementations running on resource-limited hardware. In such cases, implementations MAY limit the maximum length frame supported. However, all implementations MUST be able to receive control frames of at least 8192 octets in length.\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.2.2-Data-frames\" /\u003e2.2.2 Data frames\u003c/h3\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|C| Stream-ID (31bits) |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Data |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: For data frames this value is always 0.\u003c/p\u003e\u003cp\u003eStream-ID: A 31-bit value identifying the stream.\u003c/p\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - signifies that this frame represents the last frame to be transmitted on this stream. See Stream Close (Section 2.3.7) below.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field. The total size of a data frame is 8 bytes + length. It is valid to have a zero-length data frame.\u003c/p\u003e\u003cp\u003eData: The variable-length data payload; the length was defined in the length field.\u003c/p\u003e\u003cp\u003eData frame processing requirements:\u003c/p\u003e\u003cul\u003e\u003cli\u003eIf an endpoint receives a data frame for a stream-id which is not open and the endpoint has not sent a GOAWAY (Section 2.6.6) frame, it MUST issue a stream error (Section 2.4.2) with the error code INVALID_STREAM for the stream-id.\u003c/li\u003e\u003cli\u003eIf the endpoint which created the stream receives a data frame before receiving a SYN_REPLY on that stream, it is a protocol error, and the recipient MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.\u003c/li\u003e\u003cli\u003eImplementors note: If an endpoint receives multiple data frames for invalid stream-ids, it MAY close the session.\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.3-Streams\" /\u003e2.3 Streams\u003c/h2\u003e\u003cp\u003eStreams are independent sequences of bi-directional data divided into frames with several properties:\u003c/p\u003e\u003cul\u003e\u003cli\u003eStreams may be created by either the client or server.\u003c/li\u003e\u003cli\u003eStreams optionally carry a set of name/value header pairs.\u003c/li\u003e\u003cli\u003eStreams can concurrently send data interleaved with other streams.\u003c/li\u003e\u003cli\u003eStreams may be cancelled.\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.1-Stream-frames\" /\u003e2.3.1 Stream frames\u003c/h3\u003e\u003cp\u003eSPDY defines 3 control frames to manage the lifecycle of a stream:\u003c/p\u003e\u003cul\u003e\u003cli\u003eSYN_STREAM - Open a new stream\u003c/li\u003e\u003cli\u003eSYN_REPLY - Remote acknowledgement of a new, open stream\u003c/li\u003e\u003cli\u003eRST_STREAM - Close a stream\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.2-Stream-creation\" /\u003e2.3.2 Stream creation\u003c/h3\u003e\u003cp\u003eA stream is created by sending a control frame with the type set to SYN_STREAM (Section 2.6.1). If the server is initiating the stream, the Stream-ID must be even. If the client is initiating the stream, the Stream-ID must be odd. 0 is not a valid Stream-ID. Stream-IDs from each side of the connection must increase monotonically as new streams are created. E.g. Stream 2 may be created after stream 3, but stream 7 must not be created after stream 9. Stream IDs do not wrap: when a client or server cannot create a new stream id without exceeding a 31 bit value, it MUST NOT create a new stream.\u003c/p\u003e\u003cp\u003eThe stream-id MUST increase with each new stream. If an endpoint receives a SYN_STREAM with a stream id which is less than any previously received SYN_STREAM, it MUST issue a session error (Section 2.4.1) with the status PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eIt is a protocol error to send two SYN_STREAMs with the same stream-id. If a recipient receives a second SYN_STREAM for the same stream, it MUST issue a stream error Section (2.4.2) with the status code PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eUpon receipt of a SYN_STREAM, the recipient can reject the stream by sending a stream error (Section 2.4.2) with the error code REFUSED_STREAM. Note, however, that the creating endpoint may have already sent additional frames for that stream which cannot be immediately stopped.\u003c/p\u003e\u003cp\u003eOnce the stream is created, the creator may immediately send HEADERS or DATA frames for that stream, without needing to wait for the recipient to acknowledge.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-2.3.2.1-Unidirectional-streams\" /\u003e2.3.2.1 Unidirectional streams\u003c/h4\u003e\u003cp\u003eWhen an endpoint creates a stream with the FLAG_UNIDIRECTIONAL flag set, it creates a unidirectional stream which the creating endpoint can use to send frames, but the receiving endpoint cannot. The receiving endpoint is implicitly already in the half-closed (Section 2.3.6) state.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-2.3.2.2-Bidirectional-streams\" /\u003e2.3.2.2 Bidirectional streams\u003c/h4\u003e\u003cp\u003eSYN_STREAM frames which do not use the FLAG_UNIDIRECTIONAL flag are bidirectional streams. Both endpoints can send data on a bi-directional stream.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.3-Stream-priority\" /\u003e2.3.3 Stream priority\u003c/h3\u003e\u003cp\u003eThe creator of a stream assigns a priority for that stream. Priority is represented as an integer from 0 to 7. 0 represents the highest priority and 7 represents the lowest priority.\u003c/p\u003e\u003cp\u003eThe sender and recipient SHOULD use best-effort to process streams in the order of highest priority to lowest priority.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.4-Stream-headers\" /\u003e2.3.4 Stream headers\u003c/h3\u003e\u003cp\u003eStreams carry optional sets of name/value pair headers which carry metadata about the stream. After the stream has been created, and as long as the sender is not closed (Section 2.3.7) or half-closed (Section 2.3.6), each side may send HEADERS frame(s) containing the header data. Header data can be sent in multiple HEADERS frames, and HEADERS frames may be interleaved with data frames.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.5-Stream-data-exchange\" /\u003e2.3.5 Stream data exchange\u003c/h3\u003e\u003cp\u003eOnce a stream is created, it can be used to send arbitrary amounts of data. Generally this means that a series of data frames will be sent on the stream until a frame containing the FLAG_FIN flag is set. The FLAG_FIN can be set on a SYN_STREAM (Section 2.6.1), SYN_REPLY (Section 2.6.2), HEADERS (Section 2.6.7) or a DATA (Section 2.2.2) frame. Once the FLAG_FIN has been sent, the stream is considered to be half-closed.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.6-Stream-half-close\" /\u003e2.3.6 Stream half-close\u003c/h3\u003e\u003cp\u003eWhen one side of the stream sends a frame with the FLAG_FIN flag set, the stream is half-closed from that endpoint. The sender of the FLAG_FIN MUST NOT send further frames on that stream. When both sides have half-closed, the stream is closed. Note that WINDOW_UPDATE is metadata about a stream, and is not part of any stream, and as such is still allowed when a stream is half-closed.\u003c/p\u003e\u003cp\u003eIf an endpoint receives a data frame after the stream is half-closed from the sender (e.g. the endpoint has already received a prior frame for the stream with the FIN flag set), it MUST send a RST_STREAM to the sender with the status STREAM_ALREADY_CLOSED.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.7-Stream-close\" /\u003e2.3.7 Stream close\u003c/h3\u003e\u003cp\u003eThere are 3 ways that streams can be terminated:\u003c/p\u003e\u003cul\u003e\u003cli\u003eNormal termination: Normal stream termination occurs when both sender and recipient have half-closed the stream by sending a FLAG_FIN.\u003c/li\u003e\u003cli\u003eAbrupt termination: Either the client or server can send a RST_STREAM control frame at any time. A RST_STREAM contains an error code to indicate the reason for failure. When a RST_STREAM is sent from the stream originator, it indicates a failure to complete the stream and that no further data will be sent on the stream. When a RST_STREAM is sent from the stream recipient, the sender, upon receipt, should stop sending any data on the stream. The stream recipient should be aware that there is a race between data already in transit from the sender and the time the RST_STREAM is received. See Stream Error Handling (Section 2.4.2)\u003c/li\u003e\u003cli\u003eTCP connection teardown: If the TCP connection is torn down while un-closed streams exist, then the endpoint must assume that the stream was abnormally interrupted and may be incomplete.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eIf an endpoint receives a data frame after the stream is closed, it must send a RST_STREAM to the sender with the status PROTOCOL_ERROR.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.4-Error-Handling\" /\u003e2.4 Error Handling\u003c/h2\u003e\u003cp\u003eThe SPDY framing layer has only two types of errors, and they are always handled consistently. Any reference in this specification to \"issue a session error\" refers to Section 2.4.1. Any reference to \"issue a stream error\" refers to Section 2.4.2.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.4.1-Session-Error-Handling\" /\u003e2.4.1 Session Error Handling\u003c/h3\u003e\u003cp\u003eA session error is any error which prevents further processing of the framing layer or which corrupts the session compression state. When a session error occurs, the endpoint encountering the error MUST first send a GOAWAY (Section 2.6.6) frame with the stream id of most recently received stream from the remote endpoint, and the error code for why the session is terminating. After sending the GOAWAY frame, the endpoint MUST close the TCP connection.\u003c/p\u003e\u003cp\u003eNote that the session compression state is dependent upon both endpoints always processing all compressed data. If an endpoint partially processes a frame containing compressed data without updating compression state properly, future control frames which use compression will be always be errored. Implementations SHOULD always try to process compressed data so that errors which could be handled as stream errors do not become session errors.\u003c/p\u003e\u003cp\u003eNote that because this GOAWAY is sent during a session error case, it is possible that the GOAWAY will not be reliably received by the receiving endpoint. It is a best-effort attempt to communicate with the remote about why the session is going down.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.4.2-Stream-Error-Handling\" /\u003e2.4.2 Stream Error Handling\u003c/h3\u003e\u003cp\u003eA stream error is an error related to a specific stream-id which does not affect processing of other streams at the framing layer. Upon a stream error, the endpoint MUST send a RST_STREAM (Section 2.6.3) frame which contains the stream id of the stream where the error occurred and the error status which caused the error. After sending the RST_STREAM, the stream is closed to the sending endpoint. After sending the RST_STREAM, if the sender receives any frames other than a RST_STREAM for that stream id, it will result in sending additional RST_STREAM frames. An endpoint MUST NOT send a RST_STREAM in response to an RST_STREAM, as doing so would lead to RST_STREAM loops. Sending a RST_STREAM does not cause the SPDY session to be closed.\u003c/p\u003e\u003cp\u003eIf an endpoint has multiple RST_STREAM frames to send in succession for the same stream-id and the same error code, it MAY coalesce them into a single RST_STREAM frame. (This can happen if a stream is closed, but the remote sends multiple data frames. There is no reason to send a RST_STREAM for each frame in succession).\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.5-Data-flow\" /\u003e2.5 Data flow\u003c/h2\u003e\u003cp\u003eBecause TCP provides a single stream of data on which SPDY multiplexes multiple logical streams, clients and servers must intelligently interleave data messages for concurrent sessions.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.6-Control-frame-types\" /\u003e2.6 Control frame types\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.1-SYN_STREAM\" /\u003e2.6.1 SYN_STREAM\u003c/h3\u003e\u003cp\u003eThe SYN_STREAM control frame allows the sender to asynchronously create a stream between the endpoints. See Stream Creation (section 2.3.2)\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n|1| version | 1 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n|X| Associated-To-Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Pri|Unused | Slot | |\r\n+-------------------+ |\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003cli\u003e0x02 \u003d FLAG_UNIDIRECTIONAL - a stream created with this flag puts the recipient in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: The length is the number of bytes which follow the length field in the frame. For SYN_STREAM frames, this is 10 bytes plus the length of the compressed Name/Value block.\u003c/p\u003e\u003cp\u003eStream-ID: The 31-bit identifier for this stream. This stream-id will be used in frames which are part of this stream.\u003c/p\u003e\u003cp\u003eAssociated-To-Stream-ID: The 31-bit identifier for a stream which this stream is associated to. If this stream is independent of all other streams, it should be 0.\u003c/p\u003e\u003cp\u003ePriority: A 3-bit priority (Section 2.3.3) field.\u003c/p\u003e\u003cp\u003eUnused: 5 bits of unused space, reserved for future use.\u003c/p\u003e\u003cp\u003eSlot: 8 bits of unused space, reserved for future use. \u003cspan style\u003d\"font-size:10pt\"\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (S\u003c/span\u003eection 2.6.10\u003cspan style\u003d\"font-size:10pt\"\u003e).\u003c/span\u003e\u003c/p\u003e\u003cp\u003eIf an endpoint receives a SYN_STREAM which is larger than the implementation supports, it MAY send a RST_STREAM with error code FRAME_TOO_LARGE. All implementations MUST support the minimum size limits defined in the Control Frames section (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eS\u003c/a\u003eection 2.2.1).\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.2-SYN_REPLY\" /\u003e2.6.2 SYN_REPLY\u003c/h3\u003e\u003cp\u003eSYN_REPLY indicates the acceptance of a stream creation by the recipient of a SYN_STREAM frame.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n|1| version | 2 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: The length is the number of bytes which follow the length field in the frame. For SYN_REPLY frames, this is 4 bytes plus the length of the compressed Name/Value block.\u003c/p\u003e\u003cp\u003eStream-ID: The 31-bit identifier for this stream.\u003c/p\u003e\u003cp\u003eIf an endpoint receives multiple SYN_REPLY frames for the same active stream ID, it MUST issue a stream error (Section 2.4.2) with the error code STREAM_IN_USE.\u003c/p\u003e\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).\u003c/p\u003e\u003cp\u003eIf an endpoint receives a SYN_REPLY which is larger than the implementation supports, it MAY send a RST_STREAM with error code FRAME_TOO_LARGE. All implementations MUST support the minimum size limits defined in the Control Frames section (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eS\u003c/a\u003eection 2.2.1).\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.3-RST_STREAM\" /\u003e2.6.3 RST_STREAM\u003c/h3\u003e\u003cp\u003eThe RST_STREAM frame allows for abnormal termination of a stream. When sent by the creator of a stream, it indicates the creator wishes to cancel the stream. When sent by the recipient of a stream, it indicates an error or that the recipient did not want to accept the stream, so the stream should be closed.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 3 |\r\n+----------------------------------+\r\n| Flags (8) | 8 |\r\n+----------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+----------------------------------+\r\n| Status code |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. RST_STREAM does not define any flags. This value must be 0.\u003c/p\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field. For RST_STREAM control frames, this value is always 8.\u003c/p\u003e\u003cp\u003eStream-ID: The 31-bit identifier for this stream.\u003c/p\u003e\u003cp\u003eStatus code: (32 bits) An indicator for why the stream is being terminated.The following status codes are defined:\u003c/p\u003e\u003cul\u003e\u003cli\u003e1 - PROTOCOL_ERROR. This is a generic error, and should only be used if a more specific error is not available.\u003c/li\u003e\u003cli\u003e2 - INVALID_STREAM. This is returned when a frame is received for a stream which is not active.\u003c/li\u003e\u003cli\u003e3 - REFUSED_STREAM. Indicates that the stream was refused before any processing has been done on the stream.\u003c/li\u003e\u003cli\u003e4 - UNSUPPORTED_VERSION. Indicates that the recipient of a stream does not support the SPDY version requested.\u003c/li\u003e\u003cli\u003e5 - CANCEL. Used by the creator of a stream to indicate that the stream is no longer needed.\u003c/li\u003e\u003cli\u003e6 - INTERNAL_ERROR. This is a generic error which can be used when the implementation has internally failed, not due to anything in the protocol.\u003c/li\u003e\u003cli\u003e7 - FLOW_CONTROL_ERROR. The endpoint detected that its peer violated the flow control protocol.\u003c/li\u003e\u003cli\u003e8 - STREAM_IN_USE. The endpoint received a SYN_REPLY for a stream already open.\u003c/li\u003e\u003cli\u003e9 - STREAM_ALREADY_CLOSED. The endpoint received a data or SYN_REPLY frame for a stream which is half closed.\u003c/li\u003e\u003cli\u003e10 - deprecated/unused.\u003c/li\u003e\u003cli\u003e11 - FRAME_TOO_LARGE. The endpoint received a frame which this implementation could not support. If FRAME_TOO_LARGE is sent for a SYN_STREAM, HEADERS, or SYN_REPLY frame without fully processing the compressed portion of those frames, then the compression state will be out-of-sync with the other endpoint. In this case, senders of FRAME_TOO_LARGE MUST close the session.\u003c/li\u003e\u003cli\u003eNote: 0 is not a valid status code for a RST_STREAM.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eAfter receiving a RST_STREAM on a stream, the recipient must not send additional frames for that stream, and the stream moves into the closed state.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.4-SETTINGS\" /\u003e2.6.4 SETTINGS\u003c/h3\u003e\u003cp\u003eA SETTINGS frame contains a set of id/value pairs for communicating configuration data about how the two endpoints may communicate. SETTINGS frames can be sent at any time by either endpoint, are optionally sent, and are fully asynchronous. When the server is the sender, the sender can request that configuration data be persisted by the client across SPDY sessions and returned to the server in future communications.\u003c/p\u003e\u003cp\u003ePersistence of SETTINGS ID/Value pairs is done on a per origin/IP pair (the \"origin\" is the set of scheme, host, and port from the URI. See \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eRFC6454\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e). That is, when a client connects to a server, and the server persists settings within the client, the client SHOULD return the persisted settings on future connections to the same origin AND IP address and TCP port. Clients MUST NOT request servers to use the persistence features of the SETTINGS frames, and servers MUST ignore persistence related flags sent by a client.\u003c/span\u003e\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 4 |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Number of entries |\r\n+----------------------------------+\r\n| ID/Value Pairs |\r\n| ... |\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp\u003eType: The message type for a SETTINGS message is 4.\u003c/p\u003e\u003cp\u003eFlags: FLAG_SETTINGS_CLEAR_SETTINGS (0x1): When set, the client should clear any previously persisted SETTINGS ID/Value pairs. If this frame contains ID/Value pairs with the FLAG_SETTINGS_PERSIST_VALUE set, then the client will first clear its existing, persisted settings, and then persist the values with the flag set which are contained within this frame. Because persistence is only implemented on the client, this flag can only be used when the sender is the server.\u003c/p\u003e\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field. The total size of a SETTINGS frame is 8 bytes + length.\u003c/p\u003e\u003cp\u003eNumber of entries: A 32-bit value representing the number of ID/value pairs in this message.\u003c/p\u003e\u003cp\u003eEach ID/value pair is as follows:\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e +----------------------------------+\r\n | Flags(8) | ID (24 bits) |\r\n +----------------------------------+\r\n | Value (32 bits) |\r\n +----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eFlags: An 8 bit value. Defined Flags:\u003c/p\u003e\u003cul\u003e\u003cli\u003eFLAG_SETTINGS_PERSIST_VALUE (0x1): When set, the sender of this SETTINGS frame is requesting that the recipient persist the ID/Value and return it in future SETTINGS frames sent from the sender to this recipient. Because persistence is only implemented on the client, this flag is only sent by the server.\u003c/li\u003e\u003cli\u003eFLAG_SETTINGS_PERSISTED (0x2): When set, the sender is notifying the recipient that this ID/Value pair was previously sent to the sender by the recipient with the FLAG_SETTINGS_PERSIST_VALUE, and the sender is returning it. Because persistence is only implemented on the client, this flag is only sent by the client.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eID: 24-bits in network byte order. Defined IDs:\u003c/p\u003e\u003cul\u003e\u003cli\u003e1 - SETTINGS_UPLOAD_BANDWIDTH allows the sender to send its expected upload bandwidth on this channel. This number is an estimate. The value should be the integral number of kilobytes per second that the sender predicts as an expected maximum upload channel capacity.\u003c/li\u003e\u003cli\u003e2 - SETTINGS_DOWNLOAD_BANDWIDTH allows the sender to send its expected download bandwidth on this channel. This number is an estimate. The value should be the integral number of kilobytes per second that the sender predicts as an expected maximum download channel capacity.\u003c/li\u003e\u003cli\u003e3 - SETTINGS_ROUND_TRIP_TIME allows the sender to send its expected round-trip-time on this channel. The round trip time is defined as the minimum amount of time to send a control frame from this client to the remote and receive a response. The value is represented in milliseconds.\u003c/li\u003e\u003cli\u003e4 - SETTINGS_MAX_CONCURRENT_STREAMS allows the sender to inform the remote endpoint the maximum number of remote-initiated concurrent streams which it will allow. By default there is no limit. For implementors it is recommended that this value be no smaller than 100.\u003c/li\u003e\u003cli\u003e5 - SETTINGS_CURRENT_CWND allows the sender to inform the remote endpoint of the current TCP CWND value.\u003c/li\u003e\u003cli\u003e6 - SETTINGS_DOWNLOAD_RETRANS_RATE allows the sender to inform the remote endpoint the retransmission rate (bytes retransmitted / total bytes transmitted).\u003c/li\u003e\u003cli\u003e7 - SETTINGS_INITIAL_WINDOW_SIZE allows the sender to inform the remote endpoint the initial window size (in bytes) for new streams.\u003c/li\u003e\u003cli\u003e8 - SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE allows the server to inform the client if the new size of the client certificate vector.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eValue: A 32-bit value.\u003c/p\u003e\u003cp\u003eThe message is intentionally extensible for future information which may improve client-server communications. The sender does not need to send every type of ID/value. It must only send those for which it has accurate values to convey. When multiple ID/value pairs are sent, they should be sent in order of lowest id to highest id. A single SETTINGS frame MUST not contain multiple values for the same ID. If the recipient of a SETTINGS frame discovers multiple values for the same ID, it MUST ignore all values except the first one.\u003c/p\u003e\u003cp\u003eA server may send multiple SETTINGS frames containing different ID/Value pairs. When the same ID/Value is sent twice, the most recent value overrides any previously sent values. If the server sends IDs 1, 2, and 3 with the FLAG_SETTINGS_PERSIST_VALUE in a first SETTINGS frame, and then sends IDs 4 and 5 with the FLAG_SETTINGS_PERSIST_VALUE, when the client returns the persisted state on its next SETTINGS frame, it SHOULD send all 5 settings (1, 2, 3, 4, and 5 in this example) to the server.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.5-PING\" /\u003e2.6.5 PING\u003c/h3\u003e\u003cp\u003eThe PING control frame is a mechanism for measuring a minimal round-trip time from the sender. It can be sent from the client or the server. Recipients of a PING frame should send an identical frame to the sender as soon as possible (if there is other pending data waiting to be sent, PING should take highest priority). Each ping sent by a sender should use a unique ID.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 6 |\r\n+----------------------------------+\r\n| 0 (flags) | 4 (length) |\r\n+----------------------------------|\r\n| 32-bit ID |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp\u003eType: The message type for a PING message is 6.\u003c/p\u003e\u003cp\u003eLength: This frame is always 4 bytes long.\u003c/p\u003e\u003cp\u003eID: A unique ID for this ping, represented as an unsigned 32 bit value. When the client initiates a ping, it must use an odd numbered ID. When the server initiates a ping, it must use an even numbered ping. Use of odd/even IDs is required in order to avoid accidental looping on PINGs (where each side initiates an identical PING at the same time).\u003c/p\u003e\u003cp\u003eNote: If a sender uses all possible PING ids (e.g. has sent all 2^31 possible IDs), it can wrap and start re-using IDs.\u003c/p\u003e\u003cp\u003eIf a server receives an even numbered PING which it did not initiate, it must ignore the PING. If a client receives an odd numbered PING which it did not initiate, it must ignore the PING.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.6-GOAWAY\" /\u003e2.6.6 GOAWAY\u003c/h3\u003e\u003cp\u003eThe GOAWAY control frame is a mechanism to tell the remote side of the connection to stop creating streams on this session. It can be sent from the client or the server. Once sent, the sender will not respond to any new SYN_STREAMs on this session. Recipients of a GOAWAY frame must not send additional streams on this session, although a new session can be established for new streams. The purpose of this message is to allow an endpoint to gracefully stop accepting new streams (perhaps for a reboot or maintenance), while still finishing processing of previously established streams.\u003c/p\u003e\u003cp\u003eThere is an inherent race condition between an endpoint sending SYN_STREAMs and the remote sending a GOAWAY message. To deal with this case, the GOAWAY contains a last-stream-id indicating the stream-id of the last stream which was created on the sending endpoint in this session. If the receiver of the GOAWAY sent new SYN_STREAMs for sessions after this last-stream-id, they were not processed by the server and the receiver may treat the stream as though it had never been created at all (hence the receiver may want to re-create the stream later on a new session).\u003c/p\u003e\u003cp\u003eEndpoints should always send a GOAWAY message before closing a connection so that the remote can know whether a stream has been partially processed or not. (For example, if an HTTP client sends a POST at the same time that a server closes a connection, the client cannot know if the server started to process that POST request if the server does not send a GOAWAY frame to indicate where it stopped working).\u003c/p\u003e\u003cp\u003eAfter sending a GOAWAY message, the sender must ignore all SYN_STREAM frames for new streams, and MUST NOT create any new streams.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 7 |\r\n+----------------------------------+\r\n| 0 (flags) | 8 (length) |\r\n+----------------------------------|\r\n|X| Last-good-stream-ID (31 bits) |\r\n+----------------------------------+\r\n| Status code |\r\n+----------------------------------+\r\n \u003c/pre\u003e\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp\u003eType: The message type for a GOAWAY message is 7.\u003c/p\u003e\u003cp\u003eLength: This frame is always 8 bytes long.\u003c/p\u003e\u003cp\u003eLast-good-stream-Id: \u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eThe last stream id which was accepted by the sender of the GOAWAY message\u003c/span\u003e. If no streams were replied to, this value MUST be 0.\u003c/p\u003e\u003cp\u003eStatus: The reason for closing the session.\u003c/p\u003e\u003cul\u003e\u003cli\u003e0 - OK. This is a normal session teardown.\u003c/li\u003e\u003cli\u003e1 - PROTOCOL_ERROR. This is a generic error, and should only be used if a more specific error is not available.\u003c/li\u003e\u003cli\u003e2 - INTERNAL_ERROR. This is a generic error which can be used when the implementation has internally failed, not due to anything in the protocol.\u003c/li\u003e\u003c/ul\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.7-HEADERS\" /\u003e2.6.7 HEADERS\u003c/h3\u003e\u003cp\u003eThe HEADERS frame augments a stream with additional headers. It may be optionally sent on an existing stream at any time. Specific application of the headers in this frame is application-dependent. The name/value header block within this frame is compressed.\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n|1| version | 8 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\u003cp\u003eFlags: Flags related to this frame. Valid flags are:\u003c/p\u003e\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (Section 2.3.6) state.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eLength: An unsigned 24 bit value representing the number of bytes after the length field. The minimum length of the length field is 4 (when the number of name value pairs is 0).\u003c/p\u003e\u003cp\u003eStream-ID: The stream this HEADERS block is associated with.\u003c/p\u003e\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (Section 2.6.10).\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.8-WINDOW_UPDATE\" /\u003e2.6.8 WINDOW_UPDATE\u003c/h3\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eThe WINDOW_UPDATE frame is used to implement flow control.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow control operates at two levels: on each individual stream and on the entire connection.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eBoth types of flow control are hop by hop; that is, only between the two endpoints. Intermediaries do not forward WINDOW_UPDATE frames between dependent connections. However, throttling of data transfer by any receiver can indirectly cause the propagation of flow control information toward the original sender.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow control only applies to frames that are identified as being subject to flow control. Of the frame types defined in this document, this includes only DATA frame. Frames that are exempt from flow control MUST be accepted and processed, unless the receiver is unable to assign resources to handling the frame. A receiver MAY respond with a stream error \u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13px\"\u003e(Section 2.4.2)\u003c/span\u003e or session error \u003cspan style\u003d\"font-family:Arial,Verdana,sans-serif;font-size:13px\"\u003e(Section 2.4.1)\u003c/span\u003e of type FLOW_CONTROL_ERROR if it is unable accept a frame.\u003c/p\u003e\u003cpre\u003e\u003cpre\u003e+----------------------------------+\r\n|1| version | 9 |\r\n+----------------------------------+\r\n| 0 (flags) | 8 (length) |\r\n+----------------------------------+\r\n|X| Stream-ID (31-bits) |\r\n+----------------------------------+\r\n|X| Delta-Window-Size (31-bits) |\r\n+----------------------------------+\u003c/pre\u003e \u003c/pre\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eVersion: The SPDY version number.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlags: The flags field is always zero.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eType: The message type for a WINDOW_UPDATE message is 9.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eLength: The length field is always 8 for this frame (there are always 8 bytes after the length field).\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eStream-ID: The stream ID for which this WINDOW_UPDATE control frame applies to, or 0 if applied to connection-level flow control.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eDelta-Window-Size: The additional number of bytes that the sender can transmit in addition to existing remaining window size. The legal range for this field is 1 to 2^31 - 1 (0x7fffffff) bytes.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA receiver that receives a flow controlled frame MUST always account for its contribution against the connection flow control window, unless the receiver treats this as a session error (Section 2.4.1). This is necessary even if the frame is in error. Since the sender counts the frame toward the flow control window, if the receiver does not, the flow control window at sender and receiver can become different.\u003c/p\u003e\u003ch4 style\u003d\"font-family:Times;font-size:medium\"\u003e\u003ca name\u003d\"TOC-The-Flow-Control-Window\" /\u003eThe Flow Control Window\u003c/h4\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow control in SPDY 3.1 is implemented using a window kept by each sender on every stream. The flow control window is a simple integer value that indicates how many bytes of data the sender is permitted to transmit; as such, its size is a measure of the buffering capability of the receiver.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eTwo flow control windows are applicable: the stream flow control window and the connection flow control window. The sender MUST NOT send a flow controlled frame with a length that exceeds the space available in either of the flow control windows advertised by the receiver. Frames with zero length with the END_STREAM flag set (for example, an empty data frame) MAY be sent if there is no available space in either flow control window.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFor flow control calculations, the 8 byte frame header is not counted.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eAfter sending a flow controlled frame, the sender reduces the space available in both windows by the length of the transmitted frame.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eThe receiver of a frame sends a WINDOW_UPDATE frame as it consumes data and frees up space in flow control windows. Separate WINDOW_UPDATE frames are sent for the stream and connection level flow control windows.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA sender that receives a WINDOW_UPDATE frame updates the corresponding window by the amount specified in the frame.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA sender MUST NOT allow a flow control window to exceed 2^31 - 1 bytes. If a sender receives a WINDOW_UPDATE that causes a flow control window to exceed this maximum it MUST terminate either the stream or the connection, as appropriate. For streams, the sender sends a RST_STREAM with the error code of FLOW_CONTROL_ERROR code; for the connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFlow controlled frames from the sender and WINDOW_UPDATE frames from the receiver are completely asynchronous with respect to each other. This property allows a receiver to aggressively update the window size kept by the sender to prevent streams from stalling.\u003c/p\u003e\u003ch4 style\u003d\"font-family:Times;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Initial-Flow-Control-Window-Size\" /\u003eInitial Flow Control Window Size\u003c/h4\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eWhen a SPDY/3.1 connection is first established, new streams are created with an initial flow control window size of 64KB. The connection flow control window is 64KB bytes. Both endpoints can adjust the initial window size for new streams by including a value for SETTINGS_INITIAL_WINDOW_SIZE in the SETTINGS frame that forms part of the connection header.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003ePrior to receiving a SETTINGS frame that sets a value for SETTINGS_INITIAL_WINDOW_SIZE, an endpoint can only use the default initial window size when sending flow controlled frames. Similarly, the connection flow control window is set to the default initial window size until a WINDOW_UPDATE frame is received.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA SETTINGS frame can alter the initial flow control window size for all current streams. When the value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust the size of all stream flow control windows that it maintains by the difference between the new value and the old value. A SETTINGS frame cannot alter the connection flow control window.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA change to SETTINGS_INITIAL_WINDOW_SIZE could cause the available space in a flow control window to become negative. A sender MUST track the negative flow control window, and MUST NOT send new flow controlled frames until it receives WINDOW_UPDATE frames that cause the flow control window to become positive.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eFor example, if the client sends 60KB immediately on connection establishment, and the server sets the initial window size to be 16KB, the client will recalculate the available flow control window to be -44KB on receipt of the SETTINGS frame. The client retains a negative flow control window until WINDOW_UPDATE frames restore the window to being positive, after which the client can resume sending.\u003c/p\u003e\u003ch4 style\u003d\"font-family:Times;font-size:medium\"\u003e\u003ca name\u003d\"TOC-Reducing-the-Stream-Window-Size\" /\u003eReducing the Stream Window Size\u003c/h4\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA receiver that wishes to use a smaller flow control window than the current size can send a new SETTINGS frame. However, the receiver MUST be prepared to receive data that exceeds this window size, since the sender might send data that exceeds the lower limit prior to processing the SETTINGS frame.\u003c/p\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eA receiver has two options for handling streams that exceed flow control limits:\u003c/p\u003e\u003col style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cli\u003eThe receiver can immediately send RST_STREAM with FLOW_CONTROL_ERROR error code for the affected streams.\u003c/li\u003e\u003cli\u003eThe receiver can accept the streams and tolerate the resulting head of line blocking, sending WINDOW_UPDATE frames as it consumes data.\u003c/li\u003e\u003c/ol\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eIf a receiver decides to accept streams, both sides MUST recompute the available flow control window based on the initial window size sent in the SETTINGS.\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.9-CREDENTIAL\" /\u003e2.6.9 CREDENTIAL\u003c/h3\u003e\u003cp\u003eDEPRECATED.\u003c/p\u003e\u003cp\u003e\u003cbr /\u003e\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.10-Name-Value-Header-Block\" /\u003e2.6.10 Name/Value Header Block\u003c/h3\u003e\u003cp\u003eThe Name/Value Header Block is found in the SYN_STREAM, SYN_REPLY and HEADERS control frames, and shares a common format:\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003e+------------------------------------+\r\n| Number of Name/Value pairs (int32) |\r\n+------------------------------------+\r\n| Length of name (int32) |\r\n+------------------------------------+\r\n| Name (string) |\r\n+------------------------------------+\r\n| Length of value (int32) |\r\n+------------------------------------+\r\n| Value (string) |\r\n+------------------------------------+\r\n| (repeats) |\r\n \u003c/pre\u003e\u003cp\u003eNumber of Name/Value pairs: The number of repeating name/value pairs following this field.\u003c/p\u003e\u003cp\u003eList of Name/Value pairs:\u003c/p\u003e\u003cul\u003e\u003cli\u003eLength of Name: a 32-bit value containing the number of octets in the name field. Note that in practice, this length must not exceed 2^24, as that is the maximum size of a SPDY frame.\u003c/li\u003e\u003cli\u003eName: 0 or more octets, 8-bit sequences of data, excluding 0.\u003c/li\u003e\u003cli\u003eLength of Value: a 32-bit value containing the number of octets in the value field. Note that in practice, this length must not exceed 2^24, as that is the maximum size of a SPDY frame.\u003c/li\u003e\u003cli\u003eValue: 0 or more octets, 8-bit sequences of data, excluding 0.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eEach header name must have at least one value. Header names are encoded using the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#ASCII\" rel\u003d\"nofollow\"\u003eUS-ASCII character set\u003c/a\u003e \u003ccite title\u003d\"US-ASCII. Coded Character Set - 7-Bit American Standard Code for Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.\"\u003e[ASCII]\u003c/cite\u003e and must be all lower case. The length of each name must be greater than zero. A recipient of a zero-length name MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.\u003c/p\u003e\u003cp\u003eDuplicate header names are not allowed. To send two identically named headers, send a header with two values, where the values are separated by a single NUL (0) byte. A header value can either be empty (e.g. the length is zero) or it can contain multiple, NUL-separated values, each with length greater than zero. The value never starts nor ends with a NUL character. Recipients of illegal value fields MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-2.6.10.1-Compression\" /\u003e2.6.10.1 Compression\u003c/h4\u003e\u003cp\u003eThe Name/Value Header Block is a section of the SYN_STREAM, SYN_REPLY, and HEADERS frames used to carry header meta-data. This block is always compressed using zlib compression. Within this specification, any reference to 'zlib' is referring to the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC1950\" rel\u003d\"nofollow\"\u003eZLIB Compressed Data Format Specification Version 3.3 as part of RFC1950.\u003c/a\u003e\u003c/p\u003e\u003cp\u003eFor each HEADERS compression instance, the initial state is initialized using the following \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#UDELCOMPRESSION\" rel\u003d\"nofollow\"\u003edictionary\u003c/a\u003e \u003ccite title\u003d\"A Methodology to Derive SPDY’s Initial Dictionary for Zlib Compression\"\u003e[UDELCOMPRESSION]\u003c/cite\u003e:\u003c/p\u003e\u003cdiv /\u003e\u003cpre\u003econst unsigned char SPDY_dictionary_txt[] \u003d {\r\n\t0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, \\\\ - - - - o p t i\r\n\t0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, \\\\ o n s - - - - h\r\n\t0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, \\\\ e a d - - - - p\r\n\t0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, \\\\ o s t - - - - p\r\n\t0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, \\\\ u t - - - - d e\r\n\t0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, \\\\ l e t e - - - -\r\n\t0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, \\\\ t r a c e - - -\r\n\t0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, \\\\ - a c c e p t -\r\n\t0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, \\\\ - - - a c c e p\r\n\t0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\\\ t - c h a r s e\r\n\t0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, \\\\ t - - - - a c c\r\n\t0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\\\ e p t - e n c o\r\n\t0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, \\\\ d i n g - - - -\r\n\t0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, \\\\ a c c e p t - l\r\n\t0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, \\\\ a n g u a g e -\r\n\t0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, \\\\ - - - a c c e p\r\n\t0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, \\\\ t - r a n g e s\r\n\t0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, \\\\ - - - - a g e -\r\n\t0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, \\\\ - - - a l l o w\r\n\t0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, \\\\ - - - - a u t h\r\n\t0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, \\\\ o r i z a t i o\r\n\t0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, \\\\ n - - - - c a c\r\n\t0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, \\\\ h e - c o n t r\r\n\t0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, \\\\ o l - - - - c o\r\n\t0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, \\\\ n n e c t i o n\r\n\t0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, \\\\ e n t - b a s e\r\n\t0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\\\ e n t - e n c o\r\n\t0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, \\\\ d i n g - - - -\r\n\t0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, \\\\ c o n t e n t -\r\n\t0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, \\\\ l a n g u a g e\r\n\t0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, \\\\ e n t - l e n g\r\n\t0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, \\\\ t h - - - - c o\r\n\t0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, \\\\ n t e n t - l o\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\\\ c a t i o n - -\r\n\t0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\\\ - - c o n t e n\r\n\t0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, \\\\ t - m d 5 - - -\r\n\t0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, \\\\ - c o n t e n t\r\n\t0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, \\\\ - r a n g e - -\r\n\t0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\\\ - - c o n t e n\r\n\t0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, \\\\ t - t y p e - -\r\n\t0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, \\\\ - - d a t e - -\r\n\t0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, \\\\ - - e t a g - -\r\n\t0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, \\\\ - - e x p e c t\r\n\t0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, \\\\ - - - - e x p i\r\n\t0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, \\\\ r e s - - - - f\r\n\t0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, \\\\ r o m - - - - h\r\n\t0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, \\\\ o s t - - - - i\r\n\t0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, \\\\ f - m a t c h -\r\n\t0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, \\\\ - - - i f - m o\r\n\t0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, \\\\ d i f i e d - s\r\n\t0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, \\\\ i n c e - - - -\r\n\t0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, \\\\ i f - n o n e -\r\n\t0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, \\\\ m a t c h - - -\r\n\t0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, \\\\ - i f - r a n g\r\n\t0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, \\\\ e - - - - i f -\r\n\t0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, \\\\ u n m o d i f i\r\n\t0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, \\\\ e d - s i n c e\r\n\t0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, \\\\ - - - - l a s t\r\n\t0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, \\\\ - m o d i f i e\r\n\t0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, \\\\ d - - - - l o c\r\n\t0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, \\\\ a t i o n - - -\r\n\t0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, \\\\ - m a x - f o r\r\n\t0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, \\\\ w a r d s - - -\r\n\t0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, \\\\ - p r a g m a -\r\n\t0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, \\\\ - - - p r o x y\r\n\t0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, \\\\ - a u t h e n t\r\n\t0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, \\\\ i c a t e - - -\r\n\t0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, \\\\ - p r o x y - a\r\n\t0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, \\\\ u t h o r i z a\r\n\t0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, \\\\ t i o n - - - -\r\n\t0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, \\\\ r a n g e - - -\r\n\t0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, \\\\ - r e f e r e r\r\n\t0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, \\\\ - - - - r e t r\r\n\t0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, \\\\ y - a f t e r -\r\n\t0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, \\\\ - - - s e r v e\r\n\t0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, \\\\ r - - - - t e -\r\n\t0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, \\\\ - - - t r a i l\r\n\t0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, \\\\ e r - - - - t r\r\n\t0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, \\\\ a n s f e r - e\r\n\t0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, \\\\ n c o d i n g -\r\n\t0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, \\\\ - - - u p g r a\r\n\t0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, \\\\ d e - - - - u s\r\n\t0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, \\\\ e r - a g e n t\r\n\t0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, \\\\ - - - - v a r y\r\n\t0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, \\\\ - - - - v i a -\r\n\t0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, \\\\ - - - w a r n i\r\n\t0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, \\\\ n g - - - - w w\r\n\t0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, \\\\ w - a u t h e n\r\n\t0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, \\\\ t i c a t e - -\r\n\t0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, \\\\ - - m e t h o d\r\n\t0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, \\\\ - - - - g e t -\r\n\t0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, \\\\ - - - s t a t u\r\n\t0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, \\\\ s - - - - 2 0 0\r\n\t0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, \\\\ - O K - - - - v\r\n\t0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\\\ e r s i o n - -\r\n\t0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, \\\\ - - H T T P - 1\r\n\t0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, \\\\ - 1 - - - - u r\r\n\t0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, \\\\ l - - - - p u b\r\n\t0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, \\\\ l i c - - - - s\r\n\t0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, \\\\ e t - c o o k i\r\n\t0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, \\\\ e - - - - k e e\r\n\t0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, \\\\ p - a l i v e -\r\n\t0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, \\\\ - - - o r i g i\r\n\t0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, \\\\ n 1 0 0 1 0 1 2\r\n\t0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, \\\\ 0 1 2 0 2 2 0 5\r\n\t0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, \\\\ 2 0 6 3 0 0 3 0\r\n\t0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, \\\\ 2 3 0 3 3 0 4 3\r\n\t0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, \\\\ 0 5 3 0 6 3 0 7\r\n\t0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, \\\\ 4 0 2 4 0 5 4 0\r\n\t0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, \\\\ 6 4 0 7 4 0 8 4\r\n\t0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, \\\\ 0 9 4 1 0 4 1 1\r\n\t0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, \\\\ 4 1 2 4 1 3 4 1\r\n\t0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, \\\\ 4 4 1 5 4 1 6 4\r\n\t0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, \\\\ 1 7 5 0 2 5 0 4\r\n\t0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, \\\\ 5 0 5 2 0 3 - N\r\n\t0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, \\\\ o n - A u t h o\r\n\t0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, \\\\ r i t a t i v e\r\n\t0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, \\\\ - I n f o r m a\r\n\t0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, \\\\ t i o n 2 0 4 -\r\n\t0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, \\\\ N o - C o n t e\r\n\t0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, \\\\ n t 3 0 1 - M o\r\n\t0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, \\\\ v e d - P e r m\r\n\t0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, \\\\ a n e n t l y 4\r\n\t0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, \\\\ 0 0 - B a d - R\r\n\t0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, \\\\ e q u e s t 4 0\r\n\t0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, \\\\ 1 - U n a u t h\r\n\t0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, \\\\ o r i z e d 4 0\r\n\t0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, \\\\ 3 - F o r b i d\r\n\t0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, \\\\ d e n 4 0 4 - N\r\n\t0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, \\\\ o t - F o u n d\r\n\t0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, \\\\ 5 0 0 - I n t e\r\n\t0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, \\\\ r n a l - S e r\r\n\t0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, \\\\ v e r - E r r o\r\n\t0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, \\\\ r 5 0 1 - N o t\r\n\t0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, \\\\ - I m p l e m e\r\n\t0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, \\\\ n t e d 5 0 3 -\r\n\t0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, \\\\ S e r v i c e -\r\n\t0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, \\\\ U n a v a i l a\r\n\t0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, \\\\ b l e J a n - F\r\n\t0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, \\\\ e b - M a r - A\r\n\t0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, \\\\ p r - M a y - J\r\n\t0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, \\\\ u n - J u l - A\r\n\t0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, \\\\ u g - S e p t -\r\n\t0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, \\\\ O c t - N o v -\r\n\t0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, \\\\ D e c - 0 0 - 0\r\n\t0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, \\\\ 0 - 0 0 - M o n\r\n\t0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, \\\\ - - T u e - - W\r\n\t0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, \\\\ e d - - T h u -\r\n\t0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, \\\\ - F r i - - S a\r\n\t0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, \\\\ t - - S u n - -\r\n\t0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, \\\\ G M T c h u n k\r\n\t0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, \\\\ e d - t e x t -\r\n\t0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, \\\\ h t m l - i m a\r\n\t0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, \\\\ g e - p n g - i\r\n\t0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, \\\\ m a g e - j p g\r\n\t0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, \\\\ - i m a g e - g\r\n\t0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\\\ i f - a p p l i\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\\\ c a t i o n - x\r\n\t0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\\\ m l - a p p l i\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\\\ c a t i o n - x\r\n\t0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, \\\\ h t m l - x m l\r\n\t0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, \\\\ - t e x t - p l\r\n\t0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, \\\\ a i n - t e x t\r\n\t0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, \\\\ - j a v a s c r\r\n\t0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, \\\\ i p t - p u b l\r\n\t0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, \\\\ i c p r i v a t\r\n\t0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, \\\\ e m a x - a g e\r\n\t0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, \\\\ - g z i p - d e\r\n\t0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, \\\\ f l a t e - s d\r\n\t0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\\\ c h c h a r s e\r\n\t0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, \\\\ t - u t f - 8 c\r\n\t0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, \\\\ h a r s e t - i\r\n\t0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, \\\\ s o - 8 8 5 9 -\r\n\t0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, \\\\ 1 - u t f - - -\r\n\t0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e \\\\ - e n q - 0 -\r\n};\r\n \u003c/pre\u003e\u003cp\u003eThe entire contents of the name/value header block is compressed using zlib. There is a single zlib stream for all name value pairs in one direction on a connection. SPDY uses a SYNC_FLUSH between each compressed frame.\u003c/p\u003e\u003cp\u003eImplementation notes: the compression engine can be tuned to favor speed or size. Optimizing for size increases memory use and CPU consumption. Because header blocks are generally small, implementors may want to reduce the window-size of the compression engine from the default 15bits (a 32KB window) to more like 11bits (a 2KB window). The exact setting is chosen by the compressor, the decompressor will work with any setting.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-3.-HTTP-Layering-over-SPDY\" /\u003e3. HTTP Layering over SPDY\u003c/h1\u003e\u003cp\u003eSPDY is intended to be as compatible as possible with current web-based applications. This means that, from the perspective of the server business logic or application API, the features of HTTP are unchanged. To achieve this, all of the application request and response header semantics are preserved, although the syntax of conveying those semantics has changed. Thus, the rules from the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2616\" rel\u003d\"nofollow\"\u003eHTTP/1.1 specification in RFC2616\u003c/a\u003e apply with the changes in the sections below.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.1-Connection-Management\" /\u003e3.1 Connection Management\u003c/h2\u003e\u003cp\u003eClients SHOULD NOT open more than one SPDY session to a given \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003eorigin\u003c/a\u003e concurrently.\u003c/p\u003e\u003cp\u003eNote that it is possible for one SPDY session to be finishing (e.g. a GOAWAY message has been sent, but not all streams have finished), while another SPDY session is starting.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.1.1-Use-of-GOAWAY\" /\u003e3.1.1 Use of GOAWAY\u003c/h3\u003e\u003cp\u003eSPDY provides a GOAWAY message which can be used when closing a connection from either the client or server. Without a server GOAWAY message, HTTP has a race condition where the client sends a request (a new SYN_STREAM) just as the server is closing the connection, and the client cannot know if the server received the stream or not. By using the last-stream-id in the GOAWAY, servers can indicate to the client if a request was processed or not.\u003c/p\u003e\u003cp\u003eNote that some servers will choose to send the GOAWAY and immediately terminate the connection without waiting for active streams to finish. The client will be able to determine this because SPDY streams are determinstically closed. This abrupt termination will force the client to heuristically decide whether to retry the pending requests. Clients always need to be capable of dealing with this case because they must deal with accidental connection termination cases, which are the same as the server never having sent a GOAWAY.\u003c/p\u003e\u003cp\u003eMore sophisticated servers will use GOAWAY to implement a graceful teardown. They will send the GOAWAY and provide some time for the active streams to finish before terminating the connection.\u003c/p\u003e\u003cp\u003eIf a SPDY client closes the connection, it should also send a GOAWAY message. This allows the server to know if any server-push streams were received by the client.\u003c/p\u003e\u003cp\u003eIf the endpoint closing the connection has not received any SYN_STREAMs from the remote, the GOAWAY will contain a last-stream-id of 0.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.2-HTTP-Request-Response\" /\u003e3.2 HTTP Request/Response\u003c/h2\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.1-Request\" /\u003e3.2.1 Request\u003c/h3\u003e\u003cp\u003eThe client initiates a request by sending a SYN_STREAM frame. For requests which do not contain a body, the SYN_STREAM frame MUST set the FLAG_FIN, indicating that the client intends to send no further data on this stream. For requests which do contain a body, the SYN_STREAM will not contain the FLAG_FIN, and the body will follow the SYN_STREAM in a series of DATA frames. The last DATA frame will set the FLAG_FIN to indicate the end of the body.\u003c/p\u003e\u003cp\u003eThe SYN_STREAM Name/Value section will contain all of the HTTP headers which are associated with an HTTP request. The header block in SPDY is mostly unchanged from today's HTTP header block, with the following differences:\u003c/p\u003e\u003cul\u003e\u003cli\u003eThe first line of the request is unfolded into name/value pairs like other HTTP headers and MUST be present:\u003cul\u003e\u003cli\u003e\":method\" - the HTTP method for this request (e.g. \"GET\", \"POST\", \"HEAD\", etc)\u003c/li\u003e\u003cli\u003e\":path\" - the url-path for this url with \"/\" prefixed. (See \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC3986\" rel\u003d\"nofollow\"\u003eRFC3986\u003c/a\u003e). For example, for \"http://www.google.com/search?q\u003ddogs\" the path would be \"/search?q\u003ddogs\".\u003c/li\u003e\u003cli\u003e\":version\" - the HTTP version of this request (e.g. \"HTTP/1.1\")\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003eIn addition, the following two name/value pairs must also be present in every request:\u003cul\u003e\u003cli\u003e\":host\" - the hostport (See \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC1738\" rel\u003d\"nofollow\"\u003eRFC1738\u003c/a\u003e) portion of the URL for this request (e.g. \"www.google.com:1234\"). This header is the same as the HTTP 'Host' header.\u003c/li\u003e\u003cli\u003e\":scheme\" - the scheme portion of the URL for this request (e.g. \"https\"))\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003eHeader names are all lowercase.\u003c/li\u003e\u003cli\u003eThe Connection, Host, Keep-Alive, Proxy-Connection, and Transfer-Encoding headers are not valid and MUST not be sent.\u003c/li\u003e\u003cli\u003eUser-agents MUST support gzip compression. Regardless of the Accept-Encoding sent by the user-agent, the server may always send content encoded with gzip or deflate encoding.\u003c/li\u003e\u003cli\u003eIf a server receives a request where the sum of the data frame payload lengths does not equal the size of the Content-Length header, the server MUST return a 400 (Bad Request) error.\u003c/li\u003e\u003cli\u003ePOST-specific changes:\u003cul\u003e\u003cli\u003eAlthough POSTs are inherently chunked, POST requests SHOULD also be accompanied by a Content-Length header. There are two reasons for this: First, it assists with upload progress meters for an improved user experience. But second, we know from early versions of SPDY that failure to send a content length header is incompatible with many existing HTTP server implementations. Existing user-agents do not omit the Content-Length header, and server implementations have come to depend upon this.\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eThe user-agent is free to prioritize requests as it sees fit. If the user-agent cannot make progress without receiving a resource, it should attempt to raise the priority of that resource. Resources such as images, SHOULD generally use the lowest priority.\u003c/p\u003e\u003cp\u003eIf a client sends a SYN_STREAM without all of the method, host, path, scheme, and version headers, the server MUST reply with a HTTP 400 Bad Request reply.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.2-Response\" /\u003e3.2.2 Response\u003c/h3\u003e\u003cp\u003eThe server responds to a client request with a SYN_REPLY frame. Symmetric to the client's upload stream, server will send data after the SYN_REPLY frame via a series of DATA frames, and the last data frame will contain the FLAG_FIN to indicate successful end-of-stream. If a response (like a 202 or 204 response) contains no body, the SYN_REPLY frame may contain the FLAG_FIN flag to indicate no further data will be sent on the stream.\u003c/p\u003e\u003cul\u003e\u003cli\u003eThe response status line is unfolded into name/value pairs like other HTTP headers and must be present:\u003cul\u003e\u003cli\u003e\":status\" - The HTTP response status code (e.g. \"200\" or \"200 OK\")\u003c/li\u003e\u003cli\u003e\":version\" - The HTTP response version (e.g. \"HTTP/1.1\")\u003c/li\u003e\u003c/ul\u003e\u003c/li\u003e\u003cli\u003eAll header names must be lowercase.\u003c/li\u003e\u003cli\u003eThe Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding headers are not valid and MUST not be sent.\u003c/li\u003e\u003cli\u003eResponses MAY be accompanied by a Content-Length header for advisory purposes. (e.g. for UI progress meters)\u003c/li\u003e\u003cli\u003eIf a client receives a response where the sum of the data frame payload lengths does not equal the size of the Content-Length header, the client MUST ignore the content length header.\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eIf a client receives a SYN_REPLY without a status or without a version header, the client must reply with a RST_STREAM frame indicating a PROTOCOL ERROR.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.3-Authentication\" /\u003e3.2.3 Authentication\u003c/h3\u003e\u003cp\u003eWhen a client sends a request to an origin server that requires authentication, the server can reply with a \"401 Unauthorized\" response, and include a WWW-Authenticate challenge header that defines the authentication scheme to be used. The client then retries the request with an Authorization header appropriate to the specified authentication scheme.\u003c/p\u003e\u003cp\u003eThere are four options for proxy authentication, Basic, Digest, NTLM and Negotiate (SPNEGO). The first two options were defined in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2617\" rel\u003d\"nofollow\"\u003eRFC2617\u003c/a\u003e, and are stateless. The second two options were developed by Microsoft and specified in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC4559\" rel\u003d\"nofollow\"\u003eRFC4559\u003c/a\u003e, and are stateful; otherwise known as multi-round authentication, or connection authentication.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-3.2.3.1-Stateless-Authentication\" /\u003e3.2.3.1 Stateless Authentication\u003c/h4\u003e\u003cp\u003eStateless Authentication over SPDY is identical to how it is performed over HTTP. If multiple SPDY streams are concurrently sent to a single server, each will authenticate independently, similar to how two HTTP connections would independently authenticate to a proxy server.\u003c/p\u003e\u003ch4\u003e\u003ca name\u003d\"TOC-3.2.3.2-Stateful-Authentication\" /\u003e3.2.3.2 Stateful Authentication\u003c/h4\u003e\u003cp\u003eUnfortunately, the stateful authentication mechanisms were implemented and defined in a such a way that directly violates RFC2617 - they do not include a \"realm\" as part of the request. This is problematic in SPDY because it makes it impossible for a client to disambiguate two concurrent server authentication challenges.\u003c/p\u003e\u003cp\u003eTo deal with this case, SPDY servers using Stateful Authentication MUST implement one of two changes:\u003c/p\u003e\u003cul\u003e\u003cli\u003eServers can add a \"realm\u003d\u0026lt;desired realm\u0026gt;\" header so that the two authentication requests can be disambiguated and run concurrently. Unfortunately, given how these mechanisms work, this is probably not practical.\u003c/li\u003e\u003cli\u003eUpon sending the first stateful challenge response, the server MUST buffer and defer all further frames which are not part of completing the challenge until the challenge has completed. Completing the authentication challenge may take multiple round trips. Once the client receives a \"401 Authenticate\" response for a stateful authentication type, it MUST stop sending new requests to the server until the authentication has completed by receiving a non-401 response on at least one stream.\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.3-Server-Push-Transactions\" /\u003e3.3 Server Push Transactions\u003c/h2\u003e\u003cp\u003eSPDY enables a server to send multiple replies to a client for a single request. The rationale for this feature is that sometimes a server knows that it will need to send multiple resources in response to a single request. Without server push features, the client must first download the primary resource, then discover the secondary resource(s), and request them. Pushing of resources avoids the round-trip delay, but also creates a potential race where a server can be pushing content which a user-agent is in the process of requesting. The following mechanics attempt to prevent the race condition while enabling the performance benefit.\u003c/p\u003e\u003cp\u003eBrowsers receiving a pushed response MUST validate that the server is authorized to push the URL using the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003ebrowser same-origin\u003c/a\u003e policy. For example, a SPDY connection to www.foo.com is generally not permitted to push a response for www.evil.com.\u003c/p\u003e\u003cp\u003eIf the browser accepts a pushed response (e.g. it does not send a RST_STREAM), the browser MUST attempt to cache the pushed response in same way that it would cache any other response. This means validating the response headers and inserting into the cache.\u003c/p\u003e\u003cp\u003eBecause pushed responses have no request, they have no request headers associated with them. At the framing layer, SPDY pushed streams contain an \"associated-stream-id\" which indicates the requested stream for which the pushed stream is related. The pushed stream inherits all of the headers from the associated-stream-id with the exception of \":host\", \":scheme\", and \":path\", which are provided as part of the pushed response stream headers. The browser MUST store these inherited and implied request headers with the cached resource.\u003c/p\u003e\u003cp\u003eImplementation note: With server push, it is theoretically possible for servers to push unreasonable amounts of content or resources to the user-agent. Browsers MUST implement throttles to protect against unreasonable push attacks.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.3.1-Server-implementation\" /\u003e3.3.1 Server implementation\u003c/h3\u003e\u003cp\u003eWhen the server intends to push a resource to the user-agent, it opens a new stream by sending a unidirectional SYN_STREAM. The SYN_STREAM MUST include an Associated-To-Stream-ID, and MUST set the FLAG_UNIDIRECTIONAL flag. The SYN_STREAM MUST include headers for \":scheme\", \":host\", \":path\", which represent the URL for the resource being pushed. Subsequent headers may follow in HEADERS frames. The purpose of the association is so that the user-agent can differentiate which request induced the pushed stream; without it, if the user-agent had two tabs open to the same page, each pushing unique content under a fixed URL, the user-agent would not be able to differentiate the requests.\u003c/p\u003e\u003cp\u003eThe Associated-To-Stream-ID must be the ID of an existing, open stream. The reason for this restriction is to have a clear endpoint for pushed content. If the user-agent requested a resource on stream 11, the server replies on stream 11. It can push any number of additional streams to the client before sending a FLAG_FIN on stream 11. However, once the originating stream is closed no further push streams may be associated with it. The pushed streams do not need to be closed (FIN set) before the originating stream is closed, they only need to be created before the originating stream closes.\u003c/p\u003e\u003cp\u003eIt is illegal for a server to push a resource with the Associated-To-Stream-ID of 0.\u003c/p\u003e\u003cp\u003eTo minimize race conditions with the client, the SYN_STREAM for the pushed resources MUST be sent prior to sending any content which could allow the client to discover the pushed resource and request it.\u003c/p\u003e\u003cp\u003eThe server MUST only push resources which would have been returned from a GET request.\u003c/p\u003e\u003cp\u003eNote: If the server does not have all of the Name/Value Response headers available at the time it issues the HEADERS frame for the pushed resource, it may later use an additional HEADERS frame to augment the name/value pairs to be associated with the pushed stream. The subsequent HEADERS frame(s) must not contain a header for ':host', ':scheme', or ':path' (e.g. the server can't change the identity of the resource to be pushed). The HEADERS frame must not contain duplicate headers with a previously sent HEADERS frame. The server must send a HEADERS frame including the scheme/host/port headers before sending any data frames on the stream.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-3.3.2-Client-implementation\" /\u003e3.3.2 Client implementation\u003c/h3\u003e\u003cp\u003eWhen fetching a resource the client has 3 possibilities:\u003c/p\u003e\u003cul\u003e\u003cli\u003ethe resource is not being pushed\u003c/li\u003e\u003cli\u003ethe resource is being pushed, but the data has not yet arrived\u003c/li\u003e\u003cli\u003ethe resource is being pushed, and the data has started to arrive\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eWhen a SYN_STREAM and HEADERS frame which contains an Associated-To-Stream-ID is received, the client must not issue GET requests for the resource in the pushed stream, and instead wait for the pushed stream to arrive.\u003c/p\u003e\u003cp\u003eIf a client receives a server push stream with stream-id 0, it MUST issue a session error (Section 2.4.2) with the status code PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eWhen a client receives a SYN_STREAM from the server without a the ':host', ':scheme', and ':path' headers in the Name/Value section, it MUST reply with a RST_STREAM with error code HTTP_PROTOCOL_ERROR.\u003c/p\u003e\u003cp\u003eTo cancel individual server push streams, the client can issue a stream error (Section 2.4.2) with error code CANCEL. Upon receipt, the server MUST stop sending on this stream immediately (this is an Abrupt termination).\u003c/p\u003e\u003cp\u003eTo cancel all server push streams related to a request, the client may issue a stream error (Section 2.4.2) with error code CANCEL on the associated-stream-id. By cancelling that stream, the server MUST immediately stop sending frames for any streams  with in-association-to for the original stream.\u003c/p\u003e\u003cp\u003eIf the server sends a HEADER frame containing duplicate headers with a previous HEADERS frame for the same stream, the client must issue a stream error (Section 2.4.2) with error code PROTOCOL ERROR.\u003c/p\u003e\u003cp\u003eIf the server sends a HEADERS frame after sending a data frame for the same stream, the client MAY ignore the HEADERS frame. Ignoring the HEADERS frame after a data frame prevents handling of HTTP's trailing headers (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.40).\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-4.-Design-Rationale-and-Notes\" /\u003e4. Design Rationale and Notes\u003c/h1\u003e\u003cp\u003eAuthors' notes: The notes in this section have no bearing on the SPDY protocol as specified within this document, and none of these notes should be considered authoritative about how the protocol works. However, these notes may prove useful in future debates about how to resolve protocol ambiguities or how to evolve the protocol going forward. They may be removed before the final draft.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.1-Separation-of-Framing-Layer-and-Application-Layer\" /\u003e4.1 Separation of Framing Layer and Application Layer\u003c/h2\u003e\u003cp\u003eReaders may note that this specification sometimes blends the framing layer (Section 2) with requirements of a specific application - HTTP (Section 3). This is reflected in the request/response nature of the streams, the definition of the HEADERS and compression contexts which are very similar to HTTP, and other areas as well.\u003c/p\u003e\u003cp\u003eThis blending is intentional - the primary goal of this protocol is to create a low-latency protocol for use with HTTP. Isolating the two layers is convenient for description of the protocol and how it relates to existing HTTP implementations. However, the ability to reuse the SPDY framing layer is a non goal.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.2-Error-handling---Framing-Layer\" /\u003e4.2 Error handling - Framing Layer\u003c/h2\u003e\u003cp\u003eError handling at the SPDY layer splits errors into two groups: Those that affect an individual SPDY stream, and those that do not.\u003c/p\u003e\u003cp\u003eWhen an error is confined to a single stream, but general framing is in tact, SPDY attempts to use the RST_STREAM as a mechanism to invalidate the stream but move forward without aborting the connection altogether.\u003c/p\u003e\u003cp\u003eFor errors occuring outside of a single stream context, SPDY assumes the entire session is hosed. In this case, the endpoint detecting the error should initiate a connection close.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.3-One-Connection-Per-Domain\" /\u003e4.3 One Connection Per Domain\u003c/h2\u003e\u003cp\u003eSPDY attempts to use fewer connections than other protocols have traditionally used. The rationale for this behavior is because it is very difficult to provide a consistent level of service (e.g. TCP slow-start), prioritization, or optimal compression when the client is connecting to the server through multiple channels.\u003c/p\u003e\u003cp\u003eThrough lab measurements, we have seen consistent latency benefits by using fewer connections from the client. The overall number of packets sent by SPDY can be as much as 40% less than HTTP. Handling large numbers of concurrent connections on the server also does become a scalability problem, and SPDY reduces this load.\u003c/p\u003e\u003cp\u003eThe use of multiple connections is not without benefit, however. Because SPDY multiplexes multiple, independent streams onto a single stream, it creates a potential for head-of-line blocking problems at the transport level. In tests so far, the negative effects of head-of-line blocking (especially in the presence of packet loss) is outweighed by the benefits of compression and prioritization.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.4-Fixed-vs-Variable-Length-Fields\" /\u003e4.4 Fixed vs Variable Length Fields\u003c/h2\u003e\u003cp\u003eSPDY favors use of fixed length 32bit fields in cases where smaller, variable length encodings could have been used. To some, this seems like a tragic waste of bandwidth. SPDY choses the simple encoding for speed and simplicity.\u003c/p\u003e\u003cp\u003eThe goal of SPDY is to reduce latency on the network. The overhead of SPDY frames is generally quite low. Each data frame is only an 8 byte overhead for a 1452 byte payload (~0.6%). At the time of this writing, bandwidth is already plentiful, and there is a strong trend indicating that bandwidth will continue to increase. With an average worldwide bandwidth of 1Mbps, and assuming that a variable length encoding could reduce the overhead by 50%, the latency saved by using a variable length encoding would be less than 100 nanoseconds. More interesting are the effects when the larger encodings force a packet boundary, in which case a round-trip could be induced. However, by addressing other aspects of SPDY and TCP interactions, we believe this is completely mitigated.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.5-Compression-Context-s-\" /\u003e4.5 Compression Context(s)\u003c/h2\u003e\u003cp\u003eWhen isolating the compression contexts used for communicating with multiple origins, we had a few choices to make. We could have maintained a map (or list) of compression contexts usable for each origin. The basic case is easy - each HEADERS frame would need to identify the context to use for that frame. However, compression contexts are not cheap, so the lifecycle of each context would need to be bounded. For proxy servers, where we could churn through many contexts, this would be a concern. We considered using a static set of contexts, say 16 of them, which would bound the memory use. We also considered dynamic contexts, which could be created on the fly, and would need to be subsequently destroyed. All of these are complicated, and ultimately we decided that such a mechanism creates too many problems to solve.\u003c/p\u003e\u003cp\u003eAlternatively, we've chosen the simple approach, which is to simply provide a flag for resetting the compression context. For the common case (no proxy), this fine because most requests are to the same origin and we never need to reset the context. For cases where we are using two different origins over a single SPDY session, we simply reset the compression state between each transition.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.6-Unidirectional-streams\" /\u003e4.6 Unidirectional streams\u003c/h2\u003e\u003cp\u003eMany readers notice that unidirectional streams are both a bit confusing in concept and also somewhat redundant. If the recipient of a stream doesn't wish to send data on a stream, it could simply send a SYN_REPLY with the FLAG_FIN bit set. The FLAG_UNIDIRECTIONAL is, therefore, not necessary.\u003c/p\u003e\u003cp\u003eIt is true that we don't need the UNIDIRECTIONAL markings. It is added because it avoids the recipient of pushed streams from needing to send a set of empty frames (e.g. the SYN_STREAM w/ FLAG_FIN) which otherwise serve no purpose.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.7-Data-Compression\" /\u003e4.7 Data Compression\u003c/h2\u003e\u003cp\u003eGeneric compression of data portion of the streams (as opposed to compression of the headers) without knowing the content of the stream is redundant. There is no value in compressing a stream which is already compressed. Because of this, SPDY initially allowed data compression to be optional. We included it because study of existing websites shows that many sites are not using compression as they should, and users suffer because of it. We wanted a mechanism where, at the SPDY layer, site administrators could simply force compression - it is better to compress twice than to not compress.\u003c/p\u003e\u003cp\u003eOverall, however, with this feature being optional and sometimes redundant, it was unclear if it was useful at all. We removed it from the specification.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.8-Server-Push\" /\u003e4.8 Server Push\u003c/h2\u003e\u003cp\u003eA subtle but important point is that server push streams must be declared before the associated stream is closed. The reason for this is so that proxies have a lifetime for which they can discard information about previous streams. If a pushed stream could associate itself with an already-closed stream, then endpoints would not have a specific lifecycle for when they could disavow knowledge of the streams which went before.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-5.-Security-Considerations\" /\u003e5. Security Considerations\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.1-Use-of-Same-origin-constraints\" /\u003e5.1 Use of Same-origin constraints\u003c/h2\u003e\u003cp\u003eThis specification uses the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003esame-origin policy\u003c/a\u003e in all cases where verification of content is required.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.2-HTTP-Headers-and-SPDY-Headers\" /\u003e5.2 HTTP Headers and SPDY Headers\u003c/h2\u003e\u003cp\u003eAt the application level, HTTP uses name/value pairs in its headers. Because SPDY merges the existing HTTP headers with SPDY headers, there is a possibility that some HTTP applications already use a particular header name. To avoid any conflicts, all headers introduced for layering HTTP over SPDY are prefixed with \":\". \":\" is not a valid sequence in HTTP header naming, preventing any possible conflict.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.3-Cross-Protocol-Attacks\" /\u003e5.3 Cross-Protocol Attacks\u003c/h2\u003e\u003cp\u003eBy utilizing TLS, we believe that SPDY introduces no new cross-protocol attacks. TLS encrypts the contents of all transmission (except the handshake itself), making it difficult for attackers to control the data which could be used in a cross-protocol attack.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-5.4-Server-Push-Implicit-Headers\" /\u003e5.4 Server Push Implicit Headers\u003c/h2\u003e\u003cp\u003ePushed resources do not have an associated request. In order for existing HTTP cache control validations (such as the Vary header) to work, however, all cached resources must have a set of request headers. For this reason, browsers MUST be careful to inherit request headers from the associated stream for the push. This includes the 'Cookie' header.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-6.-Privacy-Considerations\" /\u003e6. Privacy Considerations\u003c/h1\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-6.1-Long-Lived-Connections\" /\u003e6.1 Long Lived Connections\u003c/h2\u003e\u003cp\u003eSPDY aims to keep connections open longer between clients and servers in order to reduce the latency when a user makes a request. The maintenance of these connections over time could be used to expose private information. For example, a user using a browser hours after the previous user stopped using that browser may be able to learn about what the previous user was doing. This is a problem with HTTP in its current form as well, however the short lived connections make it less of a risk.\u003c/p\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-6.2-SETTINGS-frame\" /\u003e6.2 SETTINGS frame\u003c/h2\u003e\u003cp\u003eThe SPDY SETTINGS frame allows servers to store out-of-band transmitted information about the communication between client and server on the client. Although this is intended only to be used to reduce latency, renegade servers could use it as a mechanism to store identifying information about the client in future requests.\u003c/p\u003e\u003cp\u003eClients implementing privacy modes, such as Google Chrome's \"incognito mode\", may wish to disable client-persisted SETTINGS storage.\u003c/p\u003e\u003cp\u003eClients MUST clear persisted SETTINGS information when clearing the cookies.\u003c/p\u003e\u003cp\u003eTODO: Put range maximums on each type of setting to limit inappropriate uses.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-7.-Incompatibilities-with-SPDY-draft-3\" /\u003e7. Incompatibilities with SPDY draft #3\u003c/h1\u003e\u003cp style\u003d\"font-family:Times;font-size:medium\"\u003eHere is a list of the major changes between this draft and draft #3.\u003c/p\u003e\u003cul style\u003d\"font-family:Times;font-size:medium\"\u003e\u003cli\u003eRevision of flow control to include session-level flow control.\u003c/li\u003e\u003cli\u003eRemoval of CREDENTIAL frame and associated error codes.\u003c/li\u003e\u003cli\u003eGOAWAY clarified to ensure that SETTINGS and GOAWAY remain orthogonal.\u003c/li\u003e\u003c/ul\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-8.-Requirements-Notation\" /\u003e8. Requirements Notation\u003c/h1\u003e\u003cp\u003eThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this document are to be interpreted as described in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2119\" rel\u003d\"nofollow\"\u003eRFC 2119\u003c/a\u003e.\u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-9.-Acknowledgements\" /\u003e9. Acknowledgements\u003c/h1\u003e\u003cp\u003eMany individuals have contributed to the design and evolution of SPDY: Adam Langley, Wan-Teh Chang, Jim Morrison, Mark Nottingham, Alyssa Wilk, Costin Manolache, William Chan, Vitaliy Lvin, Joe Chan, Adam Barth, Ryan Hamilton, Gavin Peters, Kent Alstad, Kevin Lindsay, Paul Amer, Fan Yang, Jonathan Leighton, Hasan Khalil, Ryan \u003c/p\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-10.-Normative-References\" /\u003e10. Normative References\u003c/h1\u003e\u003ctable\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003e\u003cb\u003e[TLSNPN]\u003c/b\u003e\u003c/td\u003e\u003ctd\u003eLangley, A., “\u003ca href\u003d\"http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\" rel\u003d\"nofollow\"\u003eTLS Next Protocol Negotiation\u003c/a\u003e”, \u0026lt;\u003ca href\u003d\"http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\" rel\u003d\"nofollow\"\u003ehttp://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\u003c/a\u003e\u0026gt;.\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cb\u003e[ASCII]\u003c/b\u003e\u003c/td\u003e\u003ctd\u003e“US-ASCII. Coded Character Set - 7-Bit American Standard Code for Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.”.\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e\u003cb\u003e[UDELCOMPRESSION]\u003c/b\u003e\u003c/td\u003e\u003ctd\u003eYang, F., Amer, P., and J. Leighton, “\u003ca href\u003d\"http://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\" rel\u003d\"nofollow\"\u003eA Methodology to Derive SPDY’s Initial Dictionary for Zlib Compression\u003c/a\u003e”, \u0026lt;\u003ca href\u003d\"http://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\" rel\u003d\"nofollow\"\u003ehttp://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\u003c/a\u003e\u0026gt;.\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cbr /\u003e\u003chr /\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-11.-Errata\" /\u003e11. Errata\u003c/h1\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eSection 2.6.6 originally listed INTERNAL_ERROR as status code 11.\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003chr /\u003e\u003cdiv\u003e\u003ch1\u003e\u003ca name\u003d\"TOC-Authors-Addresses\" /\u003eAuthors' Addresses\u003c/h1\u003e\u003caddress\u003eMike Belshe Twist EMail: \u003ca href\u003d\"mailto:mbelshe@chromium.org\"\u003embelshe@chromium.org\u003c/a\u003e\u003c/address\u003e\u003caddress\u003eRoberto Peon Google, Inc EMail: \u003ca href\u003d\"mailto:fenix@google.com\"\u003efenix@google.com\u003c/a\u003e\u003c/address\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/385872135698932510"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft3-1"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4181298934531176809"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4181298934531176809"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4181298934531176809"}],"author":[{}],"sites$pageName":{"$t":"spdy-protocol-draft3-1"},"sites$revision":{"$t":"13"}},{"gd$etag":"\"Wil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1689100172383001656"},"published":{"$t":"2012-04-20T20:55:20.854Z"},"updated":{"$t":"2014-01-15T20:05:09.376Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-01-15T20:05:02.649Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"SPDY Protocol - Draft 3"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\r\n\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-left-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.-Overview\"\u003e\u003cstrong\u003e1 \u003c/strong\u003e1. Overview\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.1-Document-Organization\"\u003e\u003cstrong\u003e1.1 \u003c/strong\u003e1.1 Document Organization\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-1.2-Definitions\"\u003e\u003cstrong\u003e1.2 \u003c/strong\u003e1.2 Definitions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.-SPDY-Framing-Layer\"\u003e\u003cstrong\u003e2 \u003c/strong\u003e2. SPDY Framing Layer\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.1-Session-Connections-\"\u003e\u003cstrong\u003e2.1 \u003c/strong\u003e2.1 Session (Connections)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2-Framing\"\u003e\u003cstrong\u003e2.2 \u003c/strong\u003e2.2 Framing\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2.1-Control-frames\"\u003e\u003cstrong\u003e2.2.1 \u003c/strong\u003e2.2.1 Control frames\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.2.2-Data-frames\"\u003e\u003cstrong\u003e2.2.2 \u003c/strong\u003e2.2.2 Data frames\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3-Streams\"\u003e\u003cstrong\u003e2.3 \u003c/strong\u003e2.3 Streams\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.1-Stream-frames\"\u003e\u003cstrong\u003e2.3.1 \u003c/strong\u003e2.3.1 Stream frames\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2-Stream-creation\"\u003e\u003cstrong\u003e2.3.2 \u003c/strong\u003e2.3.2 Stream creation\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2.1-Unidirectional-streams\"\u003e\u003cstrong\u003e2.3.2.1 \u003c/strong\u003e2.3.2.1 Unidirectional streams\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.2.2-Bidirectional-streams\"\u003e\u003cstrong\u003e2.3.2.2 \u003c/strong\u003e2.3.2.2 Bidirectional streams\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.3-Stream-priority\"\u003e\u003cstrong\u003e2.3.3 \u003c/strong\u003e2.3.3 Stream priority\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.4-Stream-headers\"\u003e\u003cstrong\u003e2.3.4 \u003c/strong\u003e2.3.4 Stream headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.5-Stream-data-exchange\"\u003e\u003cstrong\u003e2.3.5 \u003c/strong\u003e2.3.5 Stream data exchange\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.6-Stream-half-close\"\u003e\u003cstrong\u003e2.3.6 \u003c/strong\u003e2.3.6 Stream half-close\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.3.7-Stream-close\"\u003e\u003cstrong\u003e2.3.7 \u003c/strong\u003e2.3.7 Stream close\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4-Error-Handling\"\u003e\u003cstrong\u003e2.4 \u003c/strong\u003e2.4 Error Handling\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4.1-Session-Error-Handling\"\u003e\u003cstrong\u003e2.4.1 \u003c/strong\u003e2.4.1 Session Error Handling\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.4.2-Stream-Error-Handling\"\u003e\u003cstrong\u003e2.4.2 \u003c/strong\u003e2.4.2 Stream Error Handling\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.5-Data-flow\"\u003e\u003cstrong\u003e2.5 \u003c/strong\u003e2.5 Data flow\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6-Control-frame-types\"\u003e\u003cstrong\u003e2.6 \u003c/strong\u003e2.6 Control frame types\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.1-SYN_STREAM\"\u003e\u003cstrong\u003e2.6.1 \u003c/strong\u003e2.6.1 SYN_STREAM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.2-SYN_REPLY\"\u003e\u003cstrong\u003e2.6.2 \u003c/strong\u003e2.6.2 SYN_REPLY\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.3-RST_STREAM\"\u003e\u003cstrong\u003e2.6.3 \u003c/strong\u003e2.6.3 RST_STREAM\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.4-SETTINGS\"\u003e\u003cstrong\u003e2.6.4 \u003c/strong\u003e2.6.4 SETTINGS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.5-PING\"\u003e\u003cstrong\u003e2.6.5 \u003c/strong\u003e2.6.5 PING\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.6-GOAWAY\"\u003e\u003cstrong\u003e2.6.6 \u003c/strong\u003e2.6.6 GOAWAY\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.7-HEADERS\"\u003e\u003cstrong\u003e2.6.7 \u003c/strong\u003e2.6.7 HEADERS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.8-WINDOW_UPDATE\"\u003e\u003cstrong\u003e2.6.8 \u003c/strong\u003e2.6.8 WINDOW_UPDATE\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.9-CREDENTIAL\"\u003e\u003cstrong\u003e2.6.9 \u003c/strong\u003e2.6.9 CREDENTIAL\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.10-Name-Value-Header-Block\"\u003e\u003cstrong\u003e2.6.10 \u003c/strong\u003e2.6.10 Name/Value Header Block\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-2.6.10.1-Compression\"\u003e\u003cstrong\u003e2.6.10.1 \u003c/strong\u003e2.6.10.1 Compression\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.-HTTP-Layering-over-SPDY\"\u003e\u003cstrong\u003e3 \u003c/strong\u003e3. HTTP Layering over SPDY\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.1-Connection-Management\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003e3.1 Connection Management\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.1.1-Use-of-GOAWAY\"\u003e\u003cstrong\u003e3.1.1 \u003c/strong\u003e3.1.1 Use of GOAWAY\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2-HTTP-Request-Response\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003e3.2 HTTP Request/Response\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.1-Request\"\u003e\u003cstrong\u003e3.2.1 \u003c/strong\u003e3.2.1 Request\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.2-Response\"\u003e\u003cstrong\u003e3.2.2 \u003c/strong\u003e3.2.2 Response\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3-Authentication\"\u003e\u003cstrong\u003e3.2.3 \u003c/strong\u003e3.2.3 Authentication\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3.1-Stateless-Authentication\"\u003e\u003cstrong\u003e3.2.3.1 \u003c/strong\u003e3.2.3.1 Stateless Authentication\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.2.3.2-Stateful-Authentication\"\u003e\u003cstrong\u003e3.2.3.2 \u003c/strong\u003e3.2.3.2 Stateful Authentication\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3-Server-Push-Transactions\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003e3.3 Server Push Transactions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3.1-Server-implementation\"\u003e\u003cstrong\u003e3.3.1 \u003c/strong\u003e3.3.1 Server implementation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-3.3.2-Client-implementation\"\u003e\u003cstrong\u003e3.3.2 \u003c/strong\u003e3.3.2 Client implementation\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.-Design-Rationale-and-Notes\"\u003e\u003cstrong\u003e4 \u003c/strong\u003e4. Design Rationale and Notes\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.1-Separation-of-Framing-Layer-and-Application-Layer\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003e4.1 Separation of Framing Layer and Application Layer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.2-Error-handling---Framing-Layer\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003e4.2 Error handling - Framing Layer\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.3-One-Connection-Per-Domain\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003e4.3 One Connection Per Domain\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.4-Fixed-vs-Variable-Length-Fields\"\u003e\u003cstrong\u003e4.4 \u003c/strong\u003e4.4 Fixed vs Variable Length Fields\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.5-Compression-Context-s-\"\u003e\u003cstrong\u003e4.5 \u003c/strong\u003e4.5 Compression Context(s)\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.6-Unidirectional-streams\"\u003e\u003cstrong\u003e4.6 \u003c/strong\u003e4.6 Unidirectional streams\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.7-Data-Compression\"\u003e\u003cstrong\u003e4.7 \u003c/strong\u003e4.7 Data Compression\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-4.8-Server-Push\"\u003e\u003cstrong\u003e4.8 \u003c/strong\u003e4.8 Server Push\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.-Security-Considerations\"\u003e\u003cstrong\u003e5 \u003c/strong\u003e5. Security Considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.1-Use-of-Same-origin-constraints\"\u003e\u003cstrong\u003e5.1 \u003c/strong\u003e5.1 Use of Same-origin constraints\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.2-HTTP-Headers-and-SPDY-Headers\"\u003e\u003cstrong\u003e5.2 \u003c/strong\u003e5.2 HTTP Headers and SPDY Headers\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.3-Cross-Protocol-Attacks\"\u003e\u003cstrong\u003e5.3 \u003c/strong\u003e5.3 Cross-Protocol Attacks\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-5.4-Server-Push-Implicit-Headers\"\u003e\u003cstrong\u003e5.4 \u003c/strong\u003e5.4 Server Push Implicit Headers\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.-Privacy-Considerations\"\u003e\u003cstrong\u003e6 \u003c/strong\u003e6. Privacy Considerations\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.1-Long-Lived-Connections\"\u003e\u003cstrong\u003e6.1 \u003c/strong\u003e6.1 Long Lived Connections\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-6.2-SETTINGS-frame\"\u003e\u003cstrong\u003e6.2 \u003c/strong\u003e6.2 SETTINGS frame\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-7.-Incompatibilities-with-SPDY-draft-2\"\u003e\u003cstrong\u003e7 \u003c/strong\u003e7. Incompatibilities with SPDY draft #2\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-8.-Requirements-Notation\"\u003e\u003cstrong\u003e8 \u003c/strong\u003e8. Requirements Notation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-9.-Acknowledgements\"\u003e\u003cstrong\u003e9 \u003c/strong\u003e9. Acknowledgements\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-10.-Normative-References\"\u003e\u003cstrong\u003e10 \u003c/strong\u003e10. Normative References\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-11.-Errata\"\u003e\u003cstrong\u003e11 \u003c/strong\u003e11. Errata\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Authors-Addresses\"\u003e\u003cstrong\u003e12 \u003c/strong\u003eAuthors' Addresses\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-1.-Overview\" /\u003e1. Overview\u003c/h1\u003e\r\n\u003cp\u003eOne\r\n of the bottlenecks of HTTP implementations is that HTTP relies on \r\nmultiple connections for concurrency. This causes several problems, \r\nincluding additional round trips for connection setup, slow-start \r\ndelays, and connection rationing by the client, where it tries to avoid \r\nopening too many connections to any single server. HTTP pipelining helps\r\n some, but only achieves partial multiplexing. In addition, pipelining \r\nhas proven non-deployable in existing browsers due to intermediary \r\ninterference.\u003c/p\u003e\r\n\u003cp\u003eSPDY adds a framing layer for\r\n multiplexing multiple, concurrent streams across a single TCP \r\nconnection (or any reliable transport stream). The framing layer is \r\noptimized for HTTP-like request-response streams, such that applications\r\n which run over HTTP today can work over SPDY with little or no change \r\non behalf of the web application writer.\u003c/p\u003e\r\n\u003cp\u003eThe SPDY session offers four improvements over HTTP: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eMultiplexed requests: There is no limit to the number of requests that can be issued concurrently over a single SPDY connection.\u003c/li\u003e\r\n\u003cli\u003ePrioritized\r\n requests: Clients can request certain resources to be delivered first. \r\nThis avoids the problem of congesting the network channel with \r\nnon-critical resources when a high-priority request is pending.\u003c/li\u003e\r\n\u003cli\u003eCompressed\r\n headers: Clients today send a significant amount of redundant data in \r\nthe form of HTTP headers. Because a single web page may require 50 or \r\n100 subrequests, this data is significant.\u003c/li\u003e\r\n\u003cli\u003eServer pushed streams: Server Push enables content to be pushed from servers to clients without a request.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eSPDY\r\n attempts to preserve the existing semantics of HTTP. All features such \r\nas cookies, ETags, Vary headers, Content-Encoding negotiations, etc work\r\n as they do with HTTP; SPDY only replaces the way the data is written to\r\n the network.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-1.1-Document-Organization\" /\u003e1.1 Document Organization\u003c/h2\u003e\r\n\u003cp\u003eThe SPDY Specification is split into two parts: a framing layer (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.-SPDY-Framing-Layer\" title\u003d\"SPDY Framing Layer\"\u003eSection 2\u003c/a\u003e), which multiplexes a TCP connection into independent, length-prefixed frames, and an HTTP layer (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-3.-HTTP-Layering-over-SPDY\" title\u003d\"HTTP Layering over SPDY\"\u003eSection 3\u003c/a\u003e),\r\n which specifies the mechanism for overlaying HTTP request/response \r\npairs on top of the framing layer. While some of the framing layer \r\nconcepts are isolated from the HTTP layer, building a generic framing \r\nlayer has not been a goal. The framing layer is tailored to the needs of\r\n the HTTP protocol and server push.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-1.2-Definitions\" /\u003e1.2 Definitions\u003c/h2\u003e\r\n\u003cp\u003e \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eclient: The endpoint initiating the SPDY session.\u003c/li\u003e\r\n\u003cli\u003econnection: A transport-level connection between two endpoints.\u003c/li\u003e\r\n\u003cli\u003eendpoint: Either the client or server of a connection.\u003c/li\u003e\r\n\u003cli\u003eframe: A header-prefixed sequence of bytes sent over a SPDY session.\u003c/li\u003e\r\n\u003cli\u003eserver: The endpoint which did not initiate the SPDY session.\u003c/li\u003e\r\n\u003cli\u003esession: A synonym for a connection.\u003c/li\u003e\r\n\u003cli\u003esession error: An error on the SPDY session.\u003c/li\u003e\r\n\u003cli\u003estream: A bi-directional flow of bytes across a virtual channel within a SPDY session.\u003c/li\u003e\r\n\u003cli\u003estream error: An error on an individual SPDY stream.\u003c/li\u003e\u003c/ul\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-2.-SPDY-Framing-Layer\" /\u003e2. SPDY Framing Layer\u003c/h1\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-2.1-Session-Connections-\" /\u003e2.1 Session (Connections)\u003c/h2\u003e\r\n\u003cp\u003eThe SPDY framing layer (or \"session\") runs atop a reliable transport layer such as TCP. The client is the TCP connection initiator. SPDY connections are persistent connections.\u003c/p\u003e\r\n\u003cp\u003eFor\r\n best performance, it is expected that clients will not close open \r\nconnections until the user navigates away from all web pages referencing\r\n a connection, or until the server closes the connection. Servers are \r\nencouraged to leave connections open for as long as possible, but can \r\nterminate idle connections if necessary. When either endpoint closes the\r\n transport-level connection, it MUST first send a GOAWAY (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.6-GOAWAY\" title\u003d\"GOAWAY\"\u003eSection 2.6.6\u003c/a\u003e) frame so that the endpoints can reliably determine if requests finished before the close.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-2.2-Framing\" /\u003e2.2 Framing\u003c/h2\u003e\r\n\u003cp\u003eOnce\r\n the connection is established, clients and servers exchange framed \r\nmessages. There are two types of frames: control frames (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eSection 2.2.1\u003c/a\u003e) and data frames (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.2-Data-frames\" title\u003d\"Data frames\"\u003eSection 2.2.2\u003c/a\u003e). Frames always have a common header which is 8 bytes in length.\u003c/p\u003e\r\n\u003cp\u003eThe\r\n first bit is a control bit indicating whether a frame is a control \r\nframe or data frame. Control frames carry a version number, a frame \r\ntype, flags, and a length. Data frames contain the stream ID, flags, and\r\n the length for the payload carried after the common header. The simple \r\nheader is designed to make reading and writing of frames easy.\u003c/p\u003e\r\n\u003cp\u003eAll\r\n integer values, including length, version, and type, are in network \r\nbyte order. SPDY does not enforce alignment of types in dynamically \r\nsized frames.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.2.1-Control-frames\" /\u003e2.2.1 Control frames\u003c/h3\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|C| Version(15bits) | Type(16bits) |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Data |\r\n+----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eControl bit: The 'C' bit is a single bit indicating if this is a control message. For control frames this value is always 1.\u003c/p\u003e\r\n\u003cp\u003eVersion: The version number of the SPDY protocol. This document describes SPDY version 3.\u003c/p\u003e\r\n\u003cp\u003eType: The type of control frame. See Control Frames (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6-Control-frame-types\" title\u003d\"Control frame types\"\u003eSection 2.6\u003c/a\u003e) for the complete list of control frames.\u003c/p\u003e\r\n\u003cp\u003eFlags: Flags related to this frame. Flags for control frames and data frames are different.\u003c/p\u003e\r\n\u003cp\u003eLength: An unsigned 24-bit value representing the number of bytes after the length field.\u003c/p\u003e\r\n\u003cp\u003eData: data associated with this control frame. The format and length of this data is controlled by the control frame type.\u003c/p\u003e\r\n\u003cp\u003eControl frame processing requirements: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eNote\r\n that full length control frames (16MB) can be large for implementations\r\n running on resource-limited hardware. In such cases, implementations \r\nMAY limit the maximum length frame supported. However, all \r\nimplementations MUST be able to receive control frames of at least 8192 \r\noctets in length.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.2.2-Data-frames\" /\u003e2.2.2 Data frames\u003c/h3\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|C| Stream-ID (31bits) |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Data |\r\n+----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eControl bit: For data frames this value is always 0.\u003c/p\u003e\r\n\u003cp\u003eStream-ID: A 31-bit value identifying the stream.\u003c/p\u003e\r\n\u003cp\u003eFlags: Flags related to this frame. Valid flags are: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - signifies that this frame represents the last frame to be transmitted on this stream. See Stream Close (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.7-Stream-close\" title\u003d\"Stream close\"\u003eSection 2.3.7\u003c/a\u003e) below.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eLength:\r\n An unsigned 24-bit value representing the number of bytes after the \r\nlength field. The total size of a data frame is 8 bytes + length. It is \r\nvalid to have a zero-length data frame.\u003c/p\u003e\r\n\u003cp\u003eData: The variable-length data payload; the length was defined in the length field.\u003c/p\u003e\r\n\u003cp\u003eData frame processing requirements: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eIf an endpoint receives a data frame for a stream-id which is not open and the endpoint has not sent a GOAWAY (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.6-GOAWAY\" title\u003d\"GOAWAY\"\u003eSection 2.6.6\u003c/a\u003e) frame, it MUST issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with the error code INVALID_STREAM for the stream-id.\u003c/li\u003e\r\n\u003cli\u003eIf\r\n the endpoint which created the stream receives a data frame before \r\nreceiving a SYN_REPLY on that stream, it is a protocol error, and the \r\nrecipient MUST issue a stream error (\u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#StreamErrorHandler\" title\u003d\"Stream Error Handling\" rel\u003d\"nofollow\"\u003eSection 2.4.2\u003c/a\u003e) with the status code PROTOCOL_ERROR for the stream-id.\u003c/li\u003e\r\n\u003cli\u003eImplementors note: If an endpoint receives multiple data frames for invalid stream-ids, it MAY close the session.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-2.3-Streams\" /\u003e2.3 Streams\u003c/h2\u003e\r\n\u003cp\u003eStreams are independent sequences of bi-directional data divided into frames with several properties: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eStreams may be created by either the client or server.\u003c/li\u003e\r\n\u003cli\u003eStreams optionally carry a set of name/value header pairs.\u003c/li\u003e\r\n\u003cli\u003eStreams can concurrently send data interleaved with other streams.\u003c/li\u003e\r\n\u003cli\u003eStreams may be cancelled.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.1-Stream-frames\" /\u003e2.3.1 Stream frames\u003c/h3\u003e\r\n\u003cp\u003eSPDY defines 3 control frames to manage the lifecycle of a stream: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eSYN_STREAM - Open a new stream\u003c/li\u003e\r\n\u003cli\u003eSYN_REPLY - Remote acknowledgement of a new, open stream\u003c/li\u003e\r\n\u003cli\u003eRST_STREAM - Close a stream\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.2-Stream-creation\" /\u003e2.3.2 Stream creation\u003c/h3\u003e\r\n\u003cp\u003eA stream is created by sending a control frame with the type set to SYN_STREAM (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.1-SYN_STREAM\" title\u003d\"SYN_STREAM\"\u003eSection 2.6.1\u003c/a\u003e).\r\n If the server is initiating the stream, the Stream-ID must be even. If \r\nthe client is initiating the stream, the Stream-ID must be odd. 0 is not\r\n a valid Stream-ID. Stream-IDs from each side of the connection must \r\nincrease monotonically as new streams are created. E.g. Stream 2 may be \r\ncreated after stream 3, but stream 7 must not be created after stream 9.\r\n Stream IDs do not wrap: when a client or server cannot create a new \r\nstream id without exceeding a 31 bit value, it MUST NOT create a new \r\nstream.\u003c/p\u003e\r\n\u003cp\u003eThe stream-id MUST increase \r\nwith each new stream. If an endpoint receives a SYN_STREAM with a stream\r\n id which is less than any previously received SYN_STREAM, it MUST issue\r\n a session error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.1-Session-Error-Handling\" title\u003d\"Session Error Handling\"\u003eSection 2.4.1\u003c/a\u003e) with the status PROTOCOL_ERROR.\u003c/p\u003e\r\n\u003cp\u003eIt\r\n is a protocol error to send two SYN_STREAMs with the same stream-id. If\r\n a recipient receives a second SYN_STREAM for the same stream, it MUST \r\nissue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with the status code PROTOCOL_ERROR.\u003c/p\u003e\r\n\u003cp\u003eUpon receipt of a SYN_STREAM, the recipient can reject the stream by sending a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e)\r\n with the error code REFUSED_STREAM. Note, however, that the creating \r\nendpoint may have already sent additional frames for that stream which \r\ncannot be immediately stopped.\u003c/p\u003e\r\n\u003cp\u003eOnce the\r\n stream is created, the creator may immediately send HEADERS or DATA \r\nframes for that stream, without needing to wait for the recipient to \r\nacknowledge.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-2.3.2.1-Unidirectional-streams\" /\u003e2.3.2.1 Unidirectional streams\u003c/h4\u003e\r\n\u003cp\u003eWhen\r\n an endpoint creates a stream with the FLAG_UNIDIRECTIONAL flag set, it \r\ncreates a unidirectional stream which the creating endpoint can use to \r\nsend frames, but the receiving endpoint cannot. The receiving endpoint \r\nis implicitly already in the half-closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.6-Stream-half-close\" title\u003d\"Stream half-close\"\u003eSection 2.3.6\u003c/a\u003e) state.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-2.3.2.2-Bidirectional-streams\" /\u003e2.3.2.2 Bidirectional streams\u003c/h4\u003e\r\n\u003cp\u003eSYN_STREAM\r\n frames which do not use the FLAG_UNIDIRECTIONAL flag are bidirectional \r\nstreams. Both endpoints can send data on a bi-directional stream.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.3-Stream-priority\" /\u003e2.3.3 Stream priority\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n creator of a stream assigns a priority for that stream. Priority is \r\nrepresented as an integer from 0 to 7. 0 represents the highest priority\r\n and 7 represents the lowest priority.\u003c/p\u003e\r\n\u003cp\u003eThe sender and recipient SHOULD use best-effort to process streams in the order of highest priority to lowest priority.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.4-Stream-headers\" /\u003e2.3.4 Stream headers\u003c/h3\u003e\r\n\u003cp\u003eStreams\r\n carry optional sets of name/value pair headers which carry metadata \r\nabout the stream. After the stream has been created, and as long as the \r\nsender is not closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.7-Stream-close\" title\u003d\"Stream close\"\u003eSection 2.3.7\u003c/a\u003e) or half-closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.6-Stream-half-close\" title\u003d\"Stream half-close\"\u003eSection 2.3.6\u003c/a\u003e),\r\n each side may send HEADERS frame(s) containing the header data. Header \r\ndata can be sent in multiple HEADERS frames, and HEADERS frames may be \r\ninterleaved with data frames.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.5-Stream-data-exchange\" /\u003e2.3.5 Stream data exchange\u003c/h3\u003e\r\n\u003cp\u003eOnce\r\n a stream is created, it can be used to send arbitrary amounts of data. \r\nGenerally this means that a series of data frames will be sent on the \r\nstream until a frame containing the FLAG_FIN flag is set. The FLAG_FIN \r\ncan be set on a SYN_STREAM (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.1-SYN_STREAM\" title\u003d\"SYN_STREAM\"\u003eSection 2.6.1\u003c/a\u003e), SYN_REPLY (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.2-SYN_REPLY\" title\u003d\"SYN_REPLY\"\u003eSection 2.6.2\u003c/a\u003e), HEADERS (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.7-HEADERS\" title\u003d\"HEADERS\"\u003eSection 2.6.7\u003c/a\u003e) or a DATA (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.2-Data-frames\" title\u003d\"Data frames\"\u003eSection 2.2.2\u003c/a\u003e) frame. Once the FLAG_FIN has been sent, the stream is considered to be half-closed.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.6-Stream-half-close\" /\u003e2.3.6 Stream half-close\u003c/h3\u003e\r\n\u003cp\u003eWhen\r\n one side of the stream sends a frame with the FLAG_FIN flag set, the \r\nstream is half-closed from that endpoint. The sender of the FLAG_FIN \r\nMUST NOT send further frames on that stream. When both sides have \r\nhalf-closed, the stream is closed.\u003c/p\u003e\r\n\u003cp\u003eIf \r\nan endpoint receives a data frame after the stream is half-closed from \r\nthe sender (e.g. the endpoint has already received a prior frame for the\r\n stream with the FIN flag set), it MUST send a RST_STREAM to the sender \r\nwith the status STREAM_ALREADY_CLOSED.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.3.7-Stream-close\" /\u003e2.3.7 Stream close\u003c/h3\u003e\r\n\u003cp\u003eThere are 3 ways that streams can be terminated: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eNormal\r\n termination: Normal stream termination occurs when both sender and \r\nrecipient have half-closed the stream by sending a FLAG_FIN.\u003c/li\u003e\r\n\u003cli\u003eAbrupt\r\n termination: Either the client or server can send a RST_STREAM control \r\nframe at any time. A RST_STREAM contains an error code to indicate the \r\nreason for failure. When a RST_STREAM is sent from the stream \r\noriginator, it indicates a failure to complete the stream and that no \r\nfurther data will be sent on the stream. When a RST_STREAM is sent from \r\nthe stream recipient, the sender, upon receipt, should stop sending any \r\ndata on the stream. The stream recipient should be aware that there is a\r\n race between data already in transit from the sender and the time the \r\nRST_STREAM is received. See Stream Error Handling (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e)\u003c/li\u003e\r\n\u003cli\u003eTCP\r\n connection teardown: If the TCP connection is torn down while un-closed\r\n streams exist, then the endpoint must assume that the stream was \r\nabnormally interrupted and may be incomplete.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eIf\r\n an endpoint receives a data frame after the stream is closed, it must \r\nsend a RST_STREAM to the sender with the status PROTOCOL_ERROR.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-2.4-Error-Handling\" /\u003e2.4 Error Handling\u003c/h2\u003e\r\n\u003cp\u003eThe\r\n SPDY framing layer has only two types of errors, and they are always \r\nhandled consistently. Any reference in this specification to \"issue a \r\nsession error\" refers to \u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.1-Session-Error-Handling\" title\u003d\"Session Error Handling\"\u003eSection 2.4.1\u003c/a\u003e. Any reference to \"issue a stream error\" refers to \u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.4.1-Session-Error-Handling\" /\u003e2.4.1 Session Error Handling\u003c/h3\u003e\r\n\u003cp\u003eA\r\n session error is any error which prevents further processing of the \r\nframing layer or which corrupts the session compression state. When a \r\nsession error occurs, the endpoint encountering the error MUST first \r\nsend a GOAWAY (\u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#GOAWAY\" title\u003d\"GOAWAY\" rel\u003d\"nofollow\"\u003eSection 2.6.6\u003c/a\u003e)\r\n frame with the stream id of most recently received stream from the \r\nremote endpoint, and the error code for why the session is terminating. \r\nAfter sending the GOAWAY frame, the endpoint MUST close the TCP \r\nconnection.\u003c/p\u003e\r\n\u003cp\u003eNote that the session \r\ncompression state is dependent upon both endpoints always processing all\r\n compressed data. If an endpoint partially processes a frame containing \r\ncompressed data without updating compression state properly, future \r\ncontrol frames which use compression will be always be errored. \r\nImplementations SHOULD always try to process compressed data so that \r\nerrors which could be handled as stream errors do not become session \r\nerrors.\u003c/p\u003e\r\n\u003cp\u003eNote that because this GOAWAY \r\nis sent during a session error case, it is possible that the GOAWAY will\r\n not be reliably received by the receiving endpoint. It is a best-effort\r\n attempt to communicate with the remote about why the session is going \r\ndown.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.4.2-Stream-Error-Handling\" /\u003e2.4.2 Stream Error Handling\u003c/h3\u003e\r\n\u003cp\u003eA\r\n stream error is an error related to a specific stream-id which does not\r\n affect processing of other streams at the framing layer. Upon a stream \r\nerror, the endpoint MUST send a RST_STREAM (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.3-RST_STREAM\" title\u003d\"RST_STREAM\"\u003eSection 2.6.3\u003c/a\u003e)\r\n frame which contains the stream id of the stream where the error \r\noccurred and the error status which caused the error. After sending the \r\nRST_STREAM, the stream is closed to the sending endpoint. After sending \r\nthe RST_STREAM, if the sender receives any frames other than a \r\nRST_STREAM for that stream id, it will result in sending additional \r\nRST_STREAM frames. An endpoint MUST NOT send a RST_STREAM in response to\r\n an RST_STREAM, as doing so would lead to RST_STREAM loops. Sending a \r\nRST_STREAM does not cause the SPDY session to be closed.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n an endpoint has multiple RST_STREAM frames to send in succession for \r\nthe same stream-id and the same error code, it MAY coalesce them into a \r\nsingle RST_STREAM frame. (This can happen if a stream is closed, but the\r\n remote sends multiple data frames. There is no reason to send a \r\nRST_STREAM for each frame in succession).\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-2.5-Data-flow\" /\u003e2.5 Data flow\u003c/h2\u003e\r\n\u003cp\u003eBecause\r\n TCP provides a single stream of data on which SPDY multiplexes multiple\r\n logical streams, clients and servers must intelligently interleave data\r\n messages for concurrent sessions.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-2.6-Control-frame-types\" /\u003e2.6 Control frame types\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.1-SYN_STREAM\" /\u003e2.6.1 SYN_STREAM\u003c/h3\u003e\r\n\u003cp\u003eThe SYN_STREAM control frame allows the sender to asynchronously create a stream between the endpoints. See Stream Creation (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.2-Stream-creation\" title\u003d\"Stream creation\"\u003eSection 2.3.2\u003c/a\u003e)\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+------------------------------------+\r\n|1| version | 1 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n|X| Associated-To-Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Pri|Unused | Slot | |\r\n+-------------------+ |\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eFlags: Flags related to this frame. Valid flags are: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.6-Stream-half-close\" title\u003d\"Stream half-close\"\u003eSection 2.3.6\u003c/a\u003e) state.\u003c/li\u003e\r\n\u003cli\u003e0x02 \u003d FLAG_UNIDIRECTIONAL - a stream created with this flag puts the recipient in the half-closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.6-Stream-half-close\" title\u003d\"Stream half-close\"\u003eSection 2.3.6\u003c/a\u003e) state.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eLength:\r\n The length is the number of bytes which follow the length field in the \r\nframe. For SYN_STREAM frames, this is 10 bytes plus the length of the \r\ncompressed Name/Value block.\u003c/p\u003e\r\n\u003cp\u003eStream-ID: The 31-bit identifier for this stream. This stream-id will be used in frames which are part of this stream.\u003c/p\u003e\r\n\u003cp\u003eAssociated-To-Stream-ID:\r\n The 31-bit identifier for a stream which this stream is associated to. \r\nIf this stream is independent of all other streams, it should be 0.\u003c/p\u003e\r\n\u003cp\u003ePriority: A 3-bit priority (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.3-Stream-priority\" title\u003d\"Stream priority\"\u003eSection 2.3.3\u003c/a\u003e) field.\u003c/p\u003e\r\n\u003cp\u003eUnused: 5 bits of unused space, reserved for future use.\u003c/p\u003e\r\n\u003cp\u003eSlot:\r\n An 8 bit unsigned integer specifying the index in the server's \r\nCREDENTIAL vector of the client certificate to be used for this request.\r\n see CREDENTIAL frame (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.9-CREDENTIAL\" title\u003d\"CREDENTIAL\"\u003eSection 2.6.9\u003c/a\u003e). The value 0 means no client certificate should be associated with this stream.\u003c/p\u003e\r\n\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.10-Name-Value-Header-Block\" title\u003d\"Name/Value Header Block\"\u003eSection 2.6.10\u003c/a\u003e).\u003c/p\u003e\r\n\u003cp\u003eIf\r\n an endpoint receives a SYN_STREAM which is larger than the \r\nimplementation supports, it MAY send a RST_STREAM with error code \r\nFRAME_TOO_LARGE. All implementations MUST support the minimum size \r\nlimits defined in the Control Frames section (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eSection 2.2.1\u003c/a\u003e).\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.2-SYN_REPLY\" /\u003e2.6.2 SYN_REPLY\u003c/h3\u003e\r\n\u003cp\u003eSYN_REPLY indicates the acceptance of a stream creation by the recipient of a SYN_STREAM frame.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+------------------------------------+\r\n|1| version | 2 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eFlags: Flags related to this frame. Valid flags are: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.6-Stream-half-close\" title\u003d\"Stream half-close\"\u003eSection 2.3.6\u003c/a\u003e) state.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eLength:\r\n The length is the number of bytes which follow the length field in the \r\nframe. For SYN_REPLY frames, this is 4 bytes plus the length of the \r\ncompressed Name/Value block.\u003c/p\u003e\r\n\u003cp\u003eStream-ID: The 31-bit identifier for this stream.\u003c/p\u003e\r\n\u003cp\u003eIf an endpoint receives multiple SYN_REPLY frames for the same active stream ID, it MUST issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with the error code STREAM_IN_USE.\u003c/p\u003e\r\n\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.10-Name-Value-Header-Block\" title\u003d\"Name/Value Header Block\"\u003eSection 2.6.10\u003c/a\u003e).\u003c/p\u003e\r\n\u003cp\u003eIf\r\n an endpoint receives a SYN_REPLY which is larger than the \r\nimplementation supports, it MAY send a RST_STREAM with error code \r\nFRAME_TOO_LARGE. All implementations MUST support the minimum size \r\nlimits defined in the Control Frames section (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.2.1-Control-frames\" title\u003d\"Control frames\"\u003eSection 2.2.1\u003c/a\u003e).\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.3-RST_STREAM\" /\u003e2.6.3 RST_STREAM\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n RST_STREAM frame allows for abnormal termination of a stream. When sent\r\n by the creator of a stream, it indicates the creator wishes to cancel \r\nthe stream. When sent by the recipient of a stream, it indicates an \r\nerror or that the recipient did not want to accept the stream, so the \r\nstream should be closed.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|1| version | 3 |\r\n+----------------------------------+\r\n| Flags (8) | 8 |\r\n+----------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+----------------------------------+\r\n| Status code |\r\n+----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eFlags: Flags related to this frame. RST_STREAM does not define any flags. This value must be 0.\u003c/p\u003e\r\n\u003cp\u003eLength:\r\n An unsigned 24-bit value representing the number of bytes after the \r\nlength field. For RST_STREAM control frames, this value is always 8.\u003c/p\u003e\r\n\u003cp\u003eStream-ID: The 31-bit identifier for this stream.\u003c/p\u003e\r\n\u003cp\u003eStatus code: (32 bits) An indicator for why the stream is being terminated.The following status codes are defined: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e1 - PROTOCOL_ERROR. This is a generic error, and should only be used if a more specific error is not available.\u003c/li\u003e\r\n\u003cli\u003e2 - INVALID_STREAM. This is returned when a frame is received for a stream which is not active.\u003c/li\u003e\r\n\u003cli\u003e3 - REFUSED_STREAM. Indicates that the stream was refused before any processing has been done on the stream.\u003c/li\u003e\r\n\u003cli\u003e4 - UNSUPPORTED_VERSION. Indicates that the recipient of a stream does not support the SPDY version requested.\u003c/li\u003e\r\n\u003cli\u003e5 - CANCEL. Used by the creator of a stream to indicate that the stream is no longer needed.\u003c/li\u003e\r\n\u003cli\u003e6\r\n - INTERNAL_ERROR. This is a generic error which can be used when the \r\nimplementation has internally failed, not due to anything in the \r\nprotocol.\u003c/li\u003e\r\n\u003cli\u003e7 - FLOW_CONTROL_ERROR. The endpoint detected that its peer violated the flow control protocol.\u003c/li\u003e\r\n\u003cli\u003e8 - STREAM_IN_USE. The endpoint received a SYN_REPLY for a stream already open.\u003c/li\u003e\r\n\u003cli\u003e9 - STREAM_ALREADY_CLOSED. The endpoint received a data or SYN_REPLY frame for a stream which is half closed.\u003c/li\u003e\r\n\u003cli\u003e10\r\n - INVALID_CREDENTIALS. The server received a request for a resource \r\nwhose origin does not have valid credentials in the client certificate \r\nvector.\u003c/li\u003e\r\n\u003cli\u003e11 - FRAME_TOO_LARGE. The endpoint received a frame \r\nwhich this implementation could not support. If FRAME_TOO_LARGE is sent \r\nfor a SYN_STREAM, HEADERS, or SYN_REPLY frame without fully processing \r\nthe compressed portion of those frames, then the compression state will \r\nbe out-of-sync with the other endpoint. In this case, senders of \r\nFRAME_TOO_LARGE MUST close the session.\u003c/li\u003e\r\n\u003cli\u003eNote: 0 is not a valid status code for a RST_STREAM.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eAfter\r\n receiving a RST_STREAM on a stream, the recipient must not send \r\nadditional frames for that stream, and the stream moves into the closed \r\nstate.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.4-SETTINGS\" /\u003e2.6.4 SETTINGS\u003c/h3\u003e\r\n\u003cp\u003eA\r\n SETTINGS frame contains a set of id/value pairs for communicating \r\nconfiguration data about how the two endpoints may communicate. SETTINGS\r\n frames can be sent at any time by either endpoint, are optionally sent,\r\n and are fully asynchronous. When the server is the sender, the sender \r\ncan request that configuration data be persisted by the client across \r\nSPDY sessions and returned to the server in future communications.\u003c/p\u003e\r\n\u003cp\u003ePersistence\r\n of SETTINGS ID/Value pairs is done on a per origin/IP pair (the \r\n\"origin\" is the set of scheme, host, and port from the URI. See \u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e RFC6454\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e).\r\n That is, when a client connects to a server, and the server persists \r\nsettings within the client, the client SHOULD return the persisted \r\nsettings on future connections to the same origin AND IP address and TCP\r\n port. Clients MUST NOT request servers to use the persistence features \r\nof the SETTINGS frames, and servers MUST ignore persistence related \r\nflags sent by a client.\u003c/span\u003e\u003c/p\u003e\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|1| version | 4 |\r\n+----------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Number of entries |\r\n+----------------------------------+\r\n| ID/Value Pairs |\r\n| ... |\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\r\n\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\r\n\u003cp\u003eType: The message type for a SETTINGS message is 4.\u003c/p\u003e\r\n\u003cp\u003eFlags:\r\n FLAG_SETTINGS_CLEAR_SETTINGS (0x1): When set, the client should clear \r\nany previously persisted SETTINGS ID/Value pairs. If this frame contains\r\n ID/Value pairs with the FLAG_SETTINGS_PERSIST_VALUE set, then the \r\nclient will first clear its existing, persisted settings, and then \r\npersist the values with the flag set which are contained within this \r\nframe. Because persistence is only implemented on the client, this flag \r\ncan only be used when the sender is the server.\u003c/p\u003e\r\n\u003cp\u003eLength:\r\n An unsigned 24-bit value representing the number of bytes after the \r\nlength field. The total size of a SETTINGS frame is 8 bytes + length.\u003c/p\u003e\r\n\u003cp\u003eNumber of entries: A 32-bit value representing the number of ID/value pairs in this message.\u003c/p\u003e\r\n\u003cp\u003eEach ID/value pair is as follows: \u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e +----------------------------------+\r\n | Flags(8) | ID (24 bits) |\r\n +----------------------------------+\r\n | Value (32 bits) |\r\n +----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eFlags: An 8 bit value. Defined Flags: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eFLAG_SETTINGS_PERSIST_VALUE\r\n (0x1): When set, the sender of this SETTINGS frame is requesting that \r\nthe recipient persist the ID/Value and return it in future SETTINGS \r\nframes sent from the sender to this recipient. Because persistence is \r\nonly implemented on the client, this flag is only sent by the server.\u003c/li\u003e\r\n\u003cli\u003eFLAG_SETTINGS_PERSISTED\r\n (0x2): When set, the sender is notifying the recipient that this \r\nID/Value pair was previously sent to the sender by the recipient with \r\nthe FLAG_SETTINGS_PERSIST_VALUE, and the sender is returning it. Because\r\n persistence is only implemented on the client, this flag is only sent \r\nby the client.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eID: 24-bits in network byte order. Defined IDs: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e1\r\n - SETTINGS_UPLOAD_BANDWIDTH allows the sender to send its expected \r\nupload bandwidth on this channel. This number is an estimate. The value \r\nshould be the integral number of kilobytes per second that the sender \r\npredicts as an expected maximum upload channel capacity.\u003c/li\u003e\r\n\u003cli\u003e2 - \r\nSETTINGS_DOWNLOAD_BANDWIDTH allows the sender to send its expected \r\ndownload bandwidth on this channel. This number is an estimate. The \r\nvalue should be the integral number of kilobytes per second that the \r\nsender predicts as an expected maximum download channel capacity.\u003c/li\u003e\r\n\u003cli\u003e3\r\n - SETTINGS_ROUND_TRIP_TIME allows the sender to send its expected \r\nround-trip-time on this channel. The round trip time is defined as the \r\nminimum amount of time to send a control frame from this client to the \r\nremote and receive a response. The value is represented in milliseconds.\u003c/li\u003e\r\n\u003cli\u003e4\r\n - SETTINGS_MAX_CONCURRENT_STREAMS allows the sender to inform the \r\nremote endpoint the maximum number of concurrent streams which it will \r\nallow. By default there is no limit. For implementors it is recommended \r\nthat this value be no smaller than 100.\u003c/li\u003e\r\n\u003cli\u003e5 - SETTINGS_CURRENT_CWND allows the sender to inform the remote endpoint of the current TCP CWND value.\u003c/li\u003e\r\n\u003cli\u003e6\r\n - SETTINGS_DOWNLOAD_RETRANS_RATE allows the sender to inform the remote\r\n endpoint the retransmission rate (bytes retransmitted / total bytes \r\ntransmitted).\u003c/li\u003e\r\n\u003cli\u003e7 - SETTINGS_INITIAL_WINDOW_SIZE allows the sender\r\n to inform the remote endpoint the initial window size (in bytes) for \r\nnew streams.\u003c/li\u003e\r\n\u003cli\u003e8 - SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE allows \r\nthe server to inform the client if the new size of the client \r\ncertificate vector.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eValue: A 32-bit value.\u003c/p\u003e\r\n\u003cp\u003eThe\r\n message is intentionally extensible for future information which may \r\nimprove client-server communications. The sender does not need to send \r\nevery type of ID/value. It must only send those for which it has \r\naccurate values to convey. When multiple ID/value pairs are sent, they \r\nshould be sent in order of lowest id to highest id. A single SETTINGS \r\nframe MUST not contain multiple values for the same ID. If the recipient\r\n of a SETTINGS frame discovers multiple values for the same ID, it MUST \r\nignore all values except the first one.\u003c/p\u003e\r\n\u003cp\u003eA\r\n server may send multiple SETTINGS frames containing different ID/Value \r\npairs. When the same ID/Value is sent twice, the most recent value \r\noverrides any previously sent values. If the server sends IDs 1, 2, and 3\r\n with the FLAG_SETTINGS_PERSIST_VALUE in a first SETTINGS frame, and \r\nthen sends IDs 4 and 5 with the FLAG_SETTINGS_PERSIST_VALUE, when the \r\nclient returns the persisted state on its next SETTINGS frame, it SHOULD\r\n send all 5 settings (1, 2, 3, 4, and 5 in this example) to the server.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.5-PING\" /\u003e2.6.5 PING\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n PING control frame is a mechanism for measuring a minimal round-trip \r\ntime from the sender. It can be sent from the client or the server. \r\nRecipients of a PING frame should send an identical frame to the sender \r\nas soon as possible (if there is other pending data waiting to be sent, \r\nPING should take highest priority). Each ping sent by a sender should \r\nuse a unique ID.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|1| version | 6 |\r\n+----------------------------------+\r\n| 0 (flags) | 4 (length) |\r\n+----------------------------------|\r\n| 32-bit ID |\r\n+----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\r\n\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\r\n\u003cp\u003eType: The message type for a PING message is 6.\u003c/p\u003e\r\n\u003cp\u003eLength: This frame is always 4 bytes long.\u003c/p\u003e\r\n\u003cp\u003eID:\r\n A unique ID for this ping, represented as an unsigned 32 bit value. \r\nWhen the client initiates a ping, it must use an odd numbered ID. When \r\nthe server initiates a ping, it must use an even numbered ping. Use of \r\nodd/even IDs is required in order to avoid accidental looping on PINGs \r\n(where each side initiates an identical PING at the same time).\u003c/p\u003e\r\n\u003cp\u003eNote: If a sender uses all possible PING ids (e.g. has sent all 2^31 possible IDs), it can wrap and start re-using IDs.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n a server receives an even numbered PING which it did not initiate, it \r\nmust ignore the PING. If a client receives an odd numbered PING which it\r\n did not initiate, it must ignore the PING.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.6-GOAWAY\" /\u003e2.6.6 GOAWAY\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n GOAWAY control frame is a mechanism to tell the remote side of the \r\nconnection to stop creating streams on this session. It can be sent from\r\n the client or the server. Once sent, the sender will not respond to any\r\n new SYN_STREAMs on this session. Recipients of a GOAWAY frame must not \r\nsend additional streams on this session, although a new session can be \r\nestablished for new streams. The purpose of this message is to allow an \r\nendpoint to gracefully stop accepting new streams (perhaps for a reboot \r\nor maintenance), while still finishing processing of previously \r\nestablished streams.\u003c/p\u003e\r\n\u003cp\u003eThere is an \r\ninherent race condition between an endpoint sending SYN_STREAMs and the \r\nremote sending a GOAWAY message. To deal with this case, the GOAWAY \r\ncontains a last-stream-id indicating the stream-id of the last stream \r\nwhich was created on the sending endpoint in this session. If the \r\nreceiver of the GOAWAY sent new SYN_STREAMs for sessions after this \r\nlast-stream-id, they were not processed by the server and the receiver \r\nmay treat the stream as though it had never been created at all (hence \r\nthe receiver may want to re-create the stream later on a new session).\u003c/p\u003e\r\n\u003cp\u003eEndpoints\r\n should always send a GOAWAY message before closing a connection so that\r\n the remote can know whether a stream has been partially processed or \r\nnot. (For example, if an HTTP client sends a POST at the same time that a\r\n server closes a connection, the client cannot know if the server \r\nstarted to process that POST request if the server does not send a \r\nGOAWAY frame to indicate where it stopped working).\u003c/p\u003e\r\n\u003cp\u003eAfter sending a GOAWAY message, the sender must ignore all SYN_STREAM frames for new streams.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|1| version | 7 |\r\n+----------------------------------+\r\n| 0 (flags) | 8 (length) |\r\n+----------------------------------|\r\n|X| Last-good-stream-ID (31 bits) |\r\n+----------------------------------+\r\n| Status code |\r\n+----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\r\n\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\r\n\u003cp\u003eType: The message type for a GOAWAY message is 7.\u003c/p\u003e\r\n\u003cp\u003eLength: This frame is always 8 bytes long.\u003c/p\u003e\r\n\u003cp\u003eLast-good-stream-Id: \u003cspan style\u003d\"font-family:arial,sans-serif\"\u003eThe last stream id which was accepted by the sender of the GOAWAY message\u003c/span\u003e. If no streams were \r\nreplied to, this value MUST be 0.\u003c/p\u003e\r\n\u003cp\u003eStatus: The reason for closing the session. \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e0 - OK. This is a normal session teardown.\u003c/li\u003e\r\n\u003cli\u003e1 - PROTOCOL_ERROR. This is a generic error, and should only be used if a more specific error is not available.\u003c/li\u003e\r\n\u003cli\u003e2 - INTERNAL_ERROR. This is a generic error which can be used when the \r\nimplementation has internally failed, not due to anything in the \r\nprotocol.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.7-HEADERS\" /\u003e2.6.7 HEADERS\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n HEADERS frame augments a stream with additional headers. It may be \r\noptionally sent on an existing stream at any time. Specific application \r\nof the headers in this frame is application-dependent. The name/value \r\nheader block within this frame is compressed.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+------------------------------------+\r\n|1| version | 8 |\r\n+------------------------------------+\r\n| Flags (8) | Length (24 bits) |\r\n+------------------------------------+\r\n|X| Stream-ID (31bits) |\r\n+------------------------------------+\r\n| Number of Name/Value pairs (int32) | \u0026lt;+\r\n+------------------------------------+ |\r\n| Length of name (int32) | | This section is the \"Name/Value\r\n+------------------------------------+ | Header Block\", and is compressed.\r\n| Name (string) | |\r\n+------------------------------------+ |\r\n| Length of value (int32) | |\r\n+------------------------------------+ |\r\n| Value (string) | |\r\n+------------------------------------+ |\r\n| (repeats) | \u0026lt;+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eFlags: Flags related to this frame. Valid flags are: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e0x01 \u003d FLAG_FIN - marks this frame as the last frame to be transmitted on this stream and puts the sender in the half-closed (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.3.6-Stream-half-close\" title\u003d\"Stream half-close\"\u003eSection 2.3.6\u003c/a\u003e) state.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eLength:\r\n An unsigned 24 bit value representing the number of bytes after the \r\nlength field. The minimum length of the length field is 4 (when the \r\nnumber of name value pairs is 0).\u003c/p\u003e\r\n\u003cp\u003eStream-ID: The stream this HEADERS block is associated with.\u003c/p\u003e\r\n\u003cp\u003eName/Value Header Block: A set of name/value pairs carried as part of the SYN_STREAM. see Name/Value Header Block (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.10-Name-Value-Header-Block\" title\u003d\"Name/Value Header Block\"\u003eSection 2.6.10\u003c/a\u003e).\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.8-WINDOW_UPDATE\" /\u003e2.6.8 WINDOW_UPDATE\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n WINDOW_UPDATE control frame is used to implement per stream flow \r\ncontrol in SPDY. Flow control in SPDY is per hop, that is, only between \r\nthe two endpoints of a SPDY connection. If there are one or more \r\nintermediaries between the client and the origin server, flow control \r\nsignals are not explicitly forwarded by the intermediaries. (However, \r\nthrottling of data transfer by any recipient may have the effect of \r\nindirectly propagating flow control information upstream back to the \r\noriginal sender.) Flow control only applies to the data portion of data \r\nframes. Recipients must buffer all control frames. If a recipient fails \r\nto buffer an entire control frame, it MUST issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with the status code FLOW_CONTROL_ERROR for the stream.\u003c/p\u003e\r\n\u003cp\u003eFlow\r\n control in SPDY is implemented by a data transfer window kept by the \r\nsender of each stream. The data transfer window is a simple uint32 that \r\nindicates how many bytes of data the sender can transmit. After a stream\r\n is created, but before any data frames have been transmitted, the \r\nsender begins with the initial window size. This window size is a \r\nmeasure of the buffering capability of the recipient. The sender must \r\nnot send a data frame with data length greater than the transfer window \r\nsize. After sending each data frame, the sender decrements its transfer \r\nwindow size by the amount of data transmitted. When the window size \r\nbecomes less than or equal to 0, the sender must pause transmitting data\r\n frames. At the other end of the stream, the recipient sends a \r\nWINDOW_UPDATE control back to notify the sender that it has consumed \r\nsome data and freed up buffer space to receive more data.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|1| version | 9 |\r\n+----------------------------------+\r\n| 0 (flags) | 8 (length) |\r\n+----------------------------------+\r\n|X| Stream-ID (31-bits) |\r\n+----------------------------------+\r\n|X| Delta-Window-Size (31-bits) |\r\n+----------------------------------+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eControl bit: The control bit is always 1 for this message.\u003c/p\u003e\r\n\u003cp\u003eVersion: The SPDY version number.\u003c/p\u003e\r\n\u003cp\u003eType: The message type for a WINDOW_UPDATE message is 9.\u003c/p\u003e\r\n\u003cp\u003eLength: The length field is always 8 for this frame (there are 8 bytes after the length field).\u003c/p\u003e\r\n\u003cp\u003eStream-ID: The stream ID that this WINDOW_UPDATE control frame is for.\u003c/p\u003e\r\n\u003cp\u003eDelta-Window-Size:\r\n The additional number of bytes that the sender can transmit in addition\r\n to existing remaining window size. The legal range for this field is 1 \r\nto 2^31 - 1 (0x7fffffff) bytes.\u003c/p\u003e\r\n\u003cp\u003eThe \r\nwindow size as kept by the sender must never exceed 2^31 (although it \r\ncan become negative in one special case). If a sender receives a \r\nWINDOW_UPDATE that causes the its window size to exceed this limit, it \r\nmust send RST_STREAM with status code FLOW_CONTROL_ERROR to terminate \r\nthe stream.\u003c/p\u003e\r\n\u003cp\u003eWhen a SPDY connection is \r\nfirst established, the default initial window size for all streams is \r\n64KB. An endpoint can use the SETTINGS control frame to adjust the \r\ninitial window size for the connection. That is, its peer can start out \r\nusing the 64KB default initial window size when sending data frames \r\nbefore receiving the SETTINGS. Because SETTINGS is asynchronous, there \r\nmay be a race condition if the recipient wants to decrease the initial \r\nwindow size, but its peer immediately sends 64KB on the creation of a \r\nnew connection, before waiting for the SETTINGS to arrive. This is one \r\ncase where the window size kept by the sender will become negative. Once\r\n the sender detects this condition, it must stop sending data frames and\r\n wait for the recipient to catch up. The recipient has two choices: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eimmediately send RST_STREAM with FLOW_CONTROL_ERROR status code.\u003c/li\u003e\r\n\u003cli\u003eallow\r\n the head of line blocking (as there is only one stream for the session \r\nand the amount of data in flight is bounded by the default initial \r\nwindow size), and send WINDOW_UPDATE as it consumes data.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eIn\r\n the case of option 2, both sides must compute the window size based on \r\nthe initial window size in the SETTINGS. For example, if the recipient \r\nsets the initial window size to be 16KB, and the sender sends 64KB \r\nimmediately on connection establishment, the sender will discover its \r\nwindow size is -48KB on receipt of the SETTINGS. As the recipient \r\nconsumes the first 16KB, it must send a WINDOW_UPDATE of 16KB back to \r\nthe sender. This interaction continues until the sender's window size \r\nbecomes positive again, and it can resume transmitting data frames.\u003c/p\u003e\r\n\u003cp\u003eAfter\r\n the recipient reads in a data frame with FLAG_FIN that marks the end of\r\n the data stream, it should not send WINDOW_UPDATE frames as it consumes\r\n the last data frame. A sender should ignore all the WINDOW_UPDATE \r\nframes associated with the stream after it send the last frame for the \r\nstream.\u003c/p\u003e\r\n\u003cp\u003eThe data frames from the \r\nsender and the WINDOW_UPDATE frames from the recipient are completely \r\nasynchronous with respect to each other. This property allows a \r\nrecipient to aggressively update the window size kept by the sender to \r\nprevent the stream from stalling.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.9-CREDENTIAL\" /\u003e2.6.9 CREDENTIAL\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n CREDENTIAL control frame is used by the client to send additional \r\nclient certificates to the server. A SPDY client may decide to send \r\nrequests for resources from different origins on the same SPDY session \r\nif it decides that that server handles both origins. For example if the \r\nIP address associated with both hostnames matches and the SSL server \r\ncertificate presented in the initial handshake is valid for both \r\nhostnames. However, because the SSL connection can contain at most one \r\nclient certificate, the client needs a mechanism to send additional \r\nclient certificates to the server.\u003c/p\u003e\r\n\u003cp\u003eThe \r\nserver is required to maintain a vector of client certificates \r\nassociated with a SPDY session. When the client needs to send a client \r\ncertificate to the server, it will send a CREDENTIAL frame that \r\nspecifies the index of the slot in which to store the certificate as \r\nwell as proof that the client posesses the corresponding private key. \r\nThe initial size of this vector must be 8. If the client provides a \r\nclient certificate during the first TLS handshake, the contents of this \r\ncertificate must be copied into the first slot (index 1) in the \r\nCREDENTIAL vector, though it may be overwritten by subsequent CREDENTIAL\r\n frames. The server must exclusively use the CREDENTIAL vector when \r\nevaluating the client certificates associated with an origin. The server\r\n may change the size of this vector by sending a SETTINGS frame with the\r\n setting SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE value specified. In the\r\n event that the new size is smaller than the current size, truncation \r\noccurs preserving lower-index slots as possible.\u003c/p\u003e\r\n\u003cp\u003eTLS\r\n renegotiation with client authentication is incompatible with SPDY \r\ngiven the multiplexed nature of SPDY. Specifically, imagine that the \r\nclient has 2 requests outstanding to the server for two different pages \r\n(in different tabs). When the renegotiation + client certificate request\r\n comes in, the browser is unable to determine which resource triggered \r\nthe client certificate request, in order to prompt the user accordingly.\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+----------------------------------+\r\n|1|000000000000011|0000000000001010|\r\n+----------------------------------+\r\n| flags (8) | Length (24 bits) |\r\n+----------------------------------+\r\n| Slot (16 bits) | |\r\n+-----------------+ |\r\n| Proof Length (32 bits) |\r\n+----------------------------------+\r\n| Proof |\r\n+----------------------------------+ \u0026lt;+\r\n| Certificate Length (32 bits) | |\r\n+----------------------------------+ | Repeated until end of frame\r\n| Certificate | |\r\n+----------------------------------+ \u0026lt;+\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eSlot: The index in the \r\nserver's client certificate vector where this certificate should be \r\nstored. If there is already a certificate stored at this index, it will \r\nbe overwritten. The index is one based, not zero based; zero is an \r\ninvalid slot index.\u003c/p\u003e\r\n\u003cp\u003eProof: \r\nCryptographic proof that the client has possession of the private key \r\nassociated with the certificate. The format is a TLS digitally-signed \r\nelement (http://tools.ietf.org/html/rfc5246#section-4.7). The signature \r\nalgorithm must be the same as that used in the CertificateVerify \r\nmessage. However, since the MD5+SHA1 signature type used in TLS 1.0 \r\nconnections can not be correctly encoded in a digitally-signed element, \r\nSHA1 must be used when MD5+SHA1 was used in the SSL connection. The \r\nsignature is calculated over a 32 byte TLS extractor value \r\n(http://tools.ietf.org/html/rfc5705) with a label of \"EXPORTER SPDY \r\ncertificate proof\" using the empty string as context. ForRSA \r\ncertificates the signature would be a PKCS#1 v1.5 signature. For ECDSA, \r\nit would be an ECDSA-Sig-Value \r\n(http://tools.ietf.org/html/rfc5480#appendix-A). For a 1024-bit RSA key,\r\n the CREDENTIAL message would be ~500 bytes.\u003c/p\u003e\r\n\u003cp\u003eCertificate:\r\n The certificate chain, starting with the leaf certificate. Each \r\ncertificate must be encoded as a 32 bit length, followed by a DER \r\nencoded certificate. The certificate must be of the same type (RSA, \r\nECDSA, etc) as the client certificate associated with the SSL \r\nconnection.\u003c/p\u003e\r\n\u003cp\u003eIf the server receives a \r\nrequest for a resource with unacceptable credential (either missing or \r\ninvalid), it must reply with a RST_STREAM frame with the status code \r\nINVALID_CREDENTIALS. Upon receipt of a RST_STREAM frame with \r\nINVALID_CREDENTIALS, the client should initiate a new stream directly to\r\n the requested origin and resend the request. Note, SPDY does not allow \r\nthe server to request different client authentication for different \r\nresources in the same origin.\u003c/p\u003e\r\n\u003cp\u003eIf the server receives an invalid CREDENTIAL frame, it MUST respond with a GOAWAY frame and shutdown the session.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-2.6.10-Name-Value-Header-Block\" /\u003e2.6.10 Name/Value Header Block\u003c/h3\u003e\r\n\u003cp\u003eThe Name/Value Header Block is found in the SYN_STREAM, SYN_REPLY and HEADERS control frames, and shares a common format:\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003e+------------------------------------+\r\n| Number of Name/Value pairs (int32) |\r\n+------------------------------------+\r\n| Length of name (int32) |\r\n+------------------------------------+\r\n| Name (string) |\r\n+------------------------------------+\r\n| Length of value (int32) |\r\n+------------------------------------+\r\n| Value (string) |\r\n+------------------------------------+\r\n| (repeats) |\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eNumber of Name/Value pairs: The number of repeating name/value pairs following this field.\u003c/p\u003e\r\n\u003cp\u003eList of Name/Value pairs: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eLength\r\n of Name: a 32-bit value containing the number of octets in the name \r\nfield. Note that in practice, this length must not exceed 2^24, as that \r\nis the maximum size of a SPDY frame.\u003c/li\u003e\r\n\u003cli\u003eName: 0 or more octets, 8-bit sequences of data, excluding 0.\u003c/li\u003e\r\n\u003cli\u003eLength\r\n of Value: a 32-bit value containing the number of octets in the value \r\nfield. Note that in practice, this length must not exceed 2^24, as that \r\nis the maximum size of a SPDY frame.\u003c/li\u003e\r\n\u003cli\u003eValue: 0 or more octets, 8-bit sequences of data, excluding 0.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eEach header name must have at least one value. Header names are encoded using the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#ASCII\" rel\u003d\"nofollow\"\u003eUS-ASCII character set\u003c/a\u003e \u003ccite title\u003d\"US-ASCII. Coded Character Set - 7-Bit American Standard Code for Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.\"\u003e[ASCII]\u003c/cite\u003e\r\n and must be all lower case. The length of each name must be greater \r\nthan zero. A recipient of a zero-length name MUST issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with the status code PROTOCOL_ERROR for the stream-id.\u003c/p\u003e\r\n\u003cp\u003eDuplicate\r\n header names are not allowed. To send two identically named headers, \r\nsend a header with two values, where the values are separated by a \r\nsingle NUL (0) byte. A header value can either be empty (e.g. the length\r\n is zero) or it can contain multiple, NUL-separated values, each with \r\nlength greater than zero. The value never starts nor ends with a NUL \r\ncharacter. Recipients of illegal value fields MUST issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with the status code PROTOCOL_ERROR for the stream-id.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-2.6.10.1-Compression\" /\u003e2.6.10.1 Compression\u003c/h4\u003e\r\n\u003cp\u003eThe\r\n Name/Value Header Block is a section of the SYN_STREAM, SYN_REPLY, and \r\nHEADERS frames used to carry header meta-data. This block is always \r\ncompressed using zlib compression. Within this specification, any \r\nreference to 'zlib' is referring to the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC1950\" rel\u003d\"nofollow\"\u003eZLIB Compressed Data Format Specification Version 3.3 as part of RFC1950.\u003c/a\u003e\u003c/p\u003e\r\n\u003cp\u003eFor each HEADERS compression instance, the initial state is initialized using the following \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#UDELCOMPRESSION\" rel\u003d\"nofollow\"\u003edictionary\u003c/a\u003e \u003ccite title\u003d\"A Methodology to Derive SPDY’s Initial Dictionary for Zlib Compression\"\u003e[UDELCOMPRESSION]\u003c/cite\u003e:\u003c/p\u003e\r\n\u003cdiv /\u003e\r\n \r\n\u003cpre\u003econst unsigned char SPDY_dictionary_txt[] \u003d {\r\n\t0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, \\\\ - - - - o p t i\r\n\t0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, \\\\ o n s - - - - h\r\n\t0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, \\\\ e a d - - - - p\r\n\t0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, \\\\ o s t - - - - p\r\n\t0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, \\\\ u t - - - - d e\r\n\t0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, \\\\ l e t e - - - -\r\n\t0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, \\\\ t r a c e - - -\r\n\t0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, \\\\ - a c c e p t -\r\n\t0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, \\\\ - - - a c c e p\r\n\t0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\\\ t - c h a r s e\r\n\t0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, \\\\ t - - - - a c c\r\n\t0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\\\ e p t - e n c o\r\n\t0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, \\\\ d i n g - - - -\r\n\t0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, \\\\ a c c e p t - l\r\n\t0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, \\\\ a n g u a g e -\r\n\t0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, \\\\ - - - a c c e p\r\n\t0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, \\\\ t - r a n g e s\r\n\t0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, \\\\ - - - - a g e -\r\n\t0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, \\\\ - - - a l l o w\r\n\t0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, \\\\ - - - - a u t h\r\n\t0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, \\\\ o r i z a t i o\r\n\t0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, \\\\ n - - - - c a c\r\n\t0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, \\\\ h e - c o n t r\r\n\t0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, \\\\ o l - - - - c o\r\n\t0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, \\\\ n n e c t i o n\r\n\t0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, \\\\ e n t - b a s e\r\n\t0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, \\\\ e n t - e n c o\r\n\t0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, \\\\ d i n g - - - -\r\n\t0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, \\\\ c o n t e n t -\r\n\t0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, \\\\ l a n g u a g e\r\n\t0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, \\\\ - - - - c o n t\r\n\t0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, \\\\ e n t - l e n g\r\n\t0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, \\\\ t h - - - - c o\r\n\t0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, \\\\ n t e n t - l o\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\\\ c a t i o n - -\r\n\t0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\\\ - - c o n t e n\r\n\t0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, \\\\ t - m d 5 - - -\r\n\t0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, \\\\ - c o n t e n t\r\n\t0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, \\\\ - r a n g e - -\r\n\t0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, \\\\ - - c o n t e n\r\n\t0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, \\\\ t - t y p e - -\r\n\t0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, \\\\ - - d a t e - -\r\n\t0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, \\\\ - - e t a g - -\r\n\t0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, \\\\ - - e x p e c t\r\n\t0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, \\\\ - - - - e x p i\r\n\t0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, \\\\ r e s - - - - f\r\n\t0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, \\\\ r o m - - - - h\r\n\t0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, \\\\ o s t - - - - i\r\n\t0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, \\\\ f - m a t c h -\r\n\t0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, \\\\ - - - i f - m o\r\n\t0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, \\\\ d i f i e d - s\r\n\t0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, \\\\ i n c e - - - -\r\n\t0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, \\\\ i f - n o n e -\r\n\t0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, \\\\ m a t c h - - -\r\n\t0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, \\\\ - i f - r a n g\r\n\t0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, \\\\ e - - - - i f -\r\n\t0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, \\\\ u n m o d i f i\r\n\t0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, \\\\ e d - s i n c e\r\n\t0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, \\\\ - - - - l a s t\r\n\t0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, \\\\ - m o d i f i e\r\n\t0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, \\\\ d - - - - l o c\r\n\t0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, \\\\ a t i o n - - -\r\n\t0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, \\\\ - m a x - f o r\r\n\t0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, \\\\ w a r d s - - -\r\n\t0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, \\\\ - p r a g m a -\r\n\t0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, \\\\ - - - p r o x y\r\n\t0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, \\\\ - a u t h e n t\r\n\t0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, \\\\ i c a t e - - -\r\n\t0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, \\\\ - p r o x y - a\r\n\t0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, \\\\ u t h o r i z a\r\n\t0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, \\\\ t i o n - - - -\r\n\t0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, \\\\ r a n g e - - -\r\n\t0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, \\\\ - r e f e r e r\r\n\t0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, \\\\ - - - - r e t r\r\n\t0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, \\\\ y - a f t e r -\r\n\t0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, \\\\ - - - s e r v e\r\n\t0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, \\\\ r - - - - t e -\r\n\t0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, \\\\ - - - t r a i l\r\n\t0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, \\\\ e r - - - - t r\r\n\t0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, \\\\ a n s f e r - e\r\n\t0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, \\\\ n c o d i n g -\r\n\t0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, \\\\ - - - u p g r a\r\n\t0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, \\\\ d e - - - - u s\r\n\t0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, \\\\ e r - a g e n t\r\n\t0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, \\\\ - - - - v a r y\r\n\t0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, \\\\ - - - - v i a -\r\n\t0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, \\\\ - - - w a r n i\r\n\t0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, \\\\ n g - - - - w w\r\n\t0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, \\\\ w - a u t h e n\r\n\t0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, \\\\ t i c a t e - -\r\n\t0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, \\\\ - - m e t h o d\r\n\t0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, \\\\ - - - - g e t -\r\n\t0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, \\\\ - - - s t a t u\r\n\t0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, \\\\ s - - - - 2 0 0\r\n\t0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, \\\\ - O K - - - - v\r\n\t0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, \\\\ e r s i o n - -\r\n\t0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, \\\\ - - H T T P - 1\r\n\t0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, \\\\ - 1 - - - - u r\r\n\t0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, \\\\ l - - - - p u b\r\n\t0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, \\\\ l i c - - - - s\r\n\t0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, \\\\ e t - c o o k i\r\n\t0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, \\\\ e - - - - k e e\r\n\t0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, \\\\ p - a l i v e -\r\n\t0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, \\\\ - - - o r i g i\r\n\t0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, \\\\ n 1 0 0 1 0 1 2\r\n\t0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, \\\\ 0 1 2 0 2 2 0 5\r\n\t0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, \\\\ 2 0 6 3 0 0 3 0\r\n\t0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, \\\\ 2 3 0 3 3 0 4 3\r\n\t0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, \\\\ 0 5 3 0 6 3 0 7\r\n\t0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, \\\\ 4 0 2 4 0 5 4 0\r\n\t0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, \\\\ 6 4 0 7 4 0 8 4\r\n\t0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, \\\\ 0 9 4 1 0 4 1 1\r\n\t0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, \\\\ 4 1 2 4 1 3 4 1\r\n\t0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, \\\\ 4 4 1 5 4 1 6 4\r\n\t0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, \\\\ 1 7 5 0 2 5 0 4\r\n\t0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, \\\\ 5 0 5 2 0 3 - N\r\n\t0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, \\\\ o n - A u t h o\r\n\t0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, \\\\ r i t a t i v e\r\n\t0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, \\\\ - I n f o r m a\r\n\t0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, \\\\ t i o n 2 0 4 -\r\n\t0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, \\\\ N o - C o n t e\r\n\t0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, \\\\ n t 3 0 1 - M o\r\n\t0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, \\\\ v e d - P e r m\r\n\t0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, \\\\ a n e n t l y 4\r\n\t0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, \\\\ 0 0 - B a d - R\r\n\t0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, \\\\ e q u e s t 4 0\r\n\t0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, \\\\ 1 - U n a u t h\r\n\t0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, \\\\ o r i z e d 4 0\r\n\t0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, \\\\ 3 - F o r b i d\r\n\t0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, \\\\ d e n 4 0 4 - N\r\n\t0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, \\\\ o t - F o u n d\r\n\t0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, \\\\ 5 0 0 - I n t e\r\n\t0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, \\\\ r n a l - S e r\r\n\t0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, \\\\ v e r - E r r o\r\n\t0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, \\\\ r 5 0 1 - N o t\r\n\t0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, \\\\ - I m p l e m e\r\n\t0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, \\\\ n t e d 5 0 3 -\r\n\t0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, \\\\ S e r v i c e -\r\n\t0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, \\\\ U n a v a i l a\r\n\t0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, \\\\ b l e J a n - F\r\n\t0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, \\\\ e b - M a r - A\r\n\t0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, \\\\ p r - M a y - J\r\n\t0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, \\\\ u n - J u l - A\r\n\t0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, \\\\ u g - S e p t -\r\n\t0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, \\\\ O c t - N o v -\r\n\t0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, \\\\ D e c - 0 0 - 0\r\n\t0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, \\\\ 0 - 0 0 - M o n\r\n\t0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, \\\\ - - T u e - - W\r\n\t0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, \\\\ e d - - T h u -\r\n\t0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, \\\\ - F r i - - S a\r\n\t0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, \\\\ t - - S u n - -\r\n\t0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, \\\\ G M T c h u n k\r\n\t0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, \\\\ e d - t e x t -\r\n\t0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, \\\\ h t m l - i m a\r\n\t0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, \\\\ g e - p n g - i\r\n\t0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, \\\\ m a g e - j p g\r\n\t0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, \\\\ - i m a g e - g\r\n\t0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\\\ i f - a p p l i\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\\\ c a t i o n - x\r\n\t0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, \\\\ m l - a p p l i\r\n\t0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, \\\\ c a t i o n - x\r\n\t0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, \\\\ h t m l - x m l\r\n\t0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, \\\\ - t e x t - p l\r\n\t0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, \\\\ a i n - t e x t\r\n\t0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, \\\\ - j a v a s c r\r\n\t0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, \\\\ i p t - p u b l\r\n\t0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, \\\\ i c p r i v a t\r\n\t0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, \\\\ e m a x - a g e\r\n\t0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, \\\\ - g z i p - d e\r\n\t0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, \\\\ f l a t e - s d\r\n\t0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, \\\\ c h c h a r s e\r\n\t0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, \\\\ t - u t f - 8 c\r\n\t0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, \\\\ h a r s e t - i\r\n\t0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, \\\\ s o - 8 8 5 9 -\r\n\t0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, \\\\ 1 - u t f - - -\r\n\t0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e \\\\ - e n q - 0 -\r\n};\r\n \u003c/pre\u003e\r\n \r\n\u003cp\u003eThe entire contents of the \r\nname/value header block is compressed using zlib. There is a single zlib\r\n stream for all name value pairs in one direction on a connection. SPDY \r\nuses a SYNC_FLUSH between each compressed frame.\u003c/p\u003e\r\n\u003cp\u003eImplementation\r\n notes: the compression engine can be tuned to favor speed or size. \r\nOptimizing for size increases memory use and CPU consumption. Because \r\nheader blocks are generally small, implementors may want to reduce the \r\nwindow-size of the compression engine from the default 15bits (a 32KB \r\nwindow) to more like 11bits (a 2KB window). The exact setting is chosen \r\nby the compressor, the decompressor will work with any setting.\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-3.-HTTP-Layering-over-SPDY\" /\u003e3. HTTP Layering over SPDY\u003c/h1\u003e\r\n\u003cp\u003eSPDY\r\n is intended to be as compatible as possible with current web-based \r\napplications. This means that, from the perspective of the server \r\nbusiness logic or application API, the features of HTTP are unchanged. \r\nTo achieve this, all of the application request and response header \r\nsemantics are preserved, although the syntax of conveying those \r\nsemantics has changed. Thus, the rules from the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2616\" rel\u003d\"nofollow\"\u003eHTTP/1.1 specification in RFC2616\u003c/a\u003e apply with the changes in the sections below.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-3.1-Connection-Management\" /\u003e3.1 Connection Management\u003c/h2\u003e\r\n\u003cp\u003eClients SHOULD NOT open more than one SPDY session to a given \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003eorigin\u003c/a\u003e concurrently.\u003c/p\u003e\r\n\u003cp\u003eNote\r\n that it is possible for one SPDY session to be finishing (e.g. a GOAWAY\r\n message has been sent, but not all streams have finished), while \r\nanother SPDY session is starting.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-3.1.1-Use-of-GOAWAY\" /\u003e3.1.1 Use of GOAWAY\u003c/h3\u003e\r\n\u003cp\u003eSPDY\r\n provides a GOAWAY message which can be used when closing a connection \r\nfrom either the client or server. Without a server GOAWAY message, HTTP \r\nhas a race condition where the client sends a request (a new SYN_STREAM)\r\n just as the server is closing the connection, and the client cannot \r\nknow if the server received the stream or not. By using the \r\nlast-stream-id in the GOAWAY, servers can indicate to the client if a \r\nrequest was processed or not.\u003c/p\u003e\r\n\u003cp\u003eNote that\r\n some servers will choose to send the GOAWAY and immediately terminate \r\nthe connection without waiting for active streams to finish. The client \r\nwill be able to determine this because SPDY streams are determinstically\r\n closed. This abrupt termination will force the client to heuristically \r\ndecide whether to retry the pending requests. Clients always need to be \r\ncapable of dealing with this case because they must deal with accidental\r\n connection termination cases, which are the same as the server never \r\nhaving sent a GOAWAY.\u003c/p\u003e\r\n\u003cp\u003eMore \r\nsophisticated servers will use GOAWAY to implement a graceful teardown. \r\nThey will send the GOAWAY and provide some time for the active streams \r\nto finish before terminating the connection.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n a SPDY client closes the connection, it should also send a GOAWAY \r\nmessage. This allows the server to know if any server-push streams were \r\nreceived by the client.\u003c/p\u003e\r\n\u003cp\u003eIf the endpoint\r\n closing the connection has not received any SYN_STREAMs from the \r\nremote, the GOAWAY will contain a last-stream-id of 0.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-3.2-HTTP-Request-Response\" /\u003e3.2 HTTP Request/Response\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.1-Request\" /\u003e3.2.1 Request\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n client initiates a request by sending a SYN_STREAM frame. For requests \r\nwhich do not contain a body, the SYN_STREAM frame MUST set the FLAG_FIN,\r\n indicating that the client intends to send no further data on this \r\nstream. For requests which do contain a body, the SYN_STREAM will not \r\ncontain the FLAG_FIN, and the body will follow the SYN_STREAM in a \r\nseries of DATA frames. The last DATA frame will set the FLAG_FIN to \r\nindicate the end of the body.\u003c/p\u003e\r\n\u003cp\u003eThe \r\nSYN_STREAM Name/Value section will contain all of the HTTP headers which\r\n are associated with an HTTP request. The header block in SPDY is mostly\r\n unchanged from today's HTTP header block, with the following \r\ndifferences: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eThe first line of the request is unfolded into name/value pairs like other HTTP headers and MUST be present: \r\n\u003cul\u003e\u003cli\u003e\":method\" - the HTTP method for this request (e.g. \"GET\", \"POST\", \"HEAD\", etc)\u003c/li\u003e\r\n\u003cli\u003e\":path\" - the url-path for this url with \"/\" prefixed. (See \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC3986\" rel\u003d\"nofollow\"\u003eRFC3986\u003c/a\u003e). For example, for \"http://www.google.com/search?q\u003ddogs\" the path would be \"/search?q\u003ddogs\".\u003c/li\u003e\r\n\u003cli\u003e\":version\" - the HTTP version of this request (e.g. \"HTTP/1.1\")\u003c/li\u003e\u003c/ul\u003e\r\n \u003c/li\u003e\r\n\u003cli\u003eIn addition, the following two name/value pairs must also be present in every request: \r\n\u003cul\u003e\u003cli\u003e\":host\" - the hostport (See \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC1738\" rel\u003d\"nofollow\"\u003eRFC1738\u003c/a\u003e) portion of the URL for this request (e.g. \"www.google.com:1234\"). This header is the same as the HTTP 'Host' header.\u003c/li\u003e\r\n\u003cli\u003e\":scheme\" - the scheme portion of the URL for this request (e.g. \"https\"))\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003eHeader names are all lowercase.\u003c/li\u003e\r\n\u003cli\u003eThe Connection, Host, Keep-Alive, Proxy-Connection, and Transfer-Encoding headers are not valid and MUST not be sent.\u003c/li\u003e\r\n\u003cli\u003eUser-agents\r\n MUST support gzip compression. Regardless of the Accept-Encoding sent \r\nby the user-agent, the server may always send content encoded with gzip \r\nor deflate encoding.\u003c/li\u003e\r\n\u003cli\u003eIf a server receives a request where the \r\nsum of the data frame payload lengths does not equal the size of the \r\nContent-Length header, the server MUST return a 400 (Bad Request) error.\u003c/li\u003e\r\n\u003cli\u003ePOST-specific changes: \r\n\u003cul\u003e\u003cli\u003eAlthough\r\n POSTs are inherently chunked, POST requests SHOULD also be accompanied \r\nby a Content-Length header. There are two reasons for this: First, it \r\nassists with upload progress meters for an improved user experience. But\r\n second, we know from early versions of SPDY that failure to send a \r\ncontent length header is incompatible with many existing HTTP server \r\nimplementations. Existing user-agents do not omit the Content-Length \r\nheader, and server implementations have come to depend upon this.\u003c/li\u003e\u003c/ul\u003e\r\n \u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eThe\r\n user-agent is free to prioritize requests as it sees fit. If the \r\nuser-agent cannot make progress without receiving a resource, it should \r\nattempt to raise the priority of that resource. Resources such as \r\nimages, SHOULD generally use the lowest priority.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n a client sends a SYN_STREAM without all of the method, host, path, \r\nscheme, and version headers, the server MUST reply with a HTTP 400 Bad \r\nRequest reply.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.2-Response\" /\u003e3.2.2 Response\u003c/h3\u003e\r\n\u003cp\u003eThe\r\n server responds to a client request with a SYN_REPLY frame. Symmetric \r\nto the client's upload stream, server will send data after the SYN_REPLY\r\n frame via a series of DATA frames, and the last data frame will contain\r\n the FLAG_FIN to indicate successful end-of-stream. If a response (like a\r\n 202 or 204 response) contains no body, the SYN_REPLY frame may contain \r\nthe FLAG_FIN flag to indicate no further data will be sent on the \r\nstream.\u003c/p\u003e\r\n\u003cp\u003e \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eThe response status line is unfolded into name/value pairs like other HTTP headers and must be present: \r\n\u003cul\u003e\u003cli\u003e\":status\" - The HTTP response status code (e.g. \"200\" or \"200 OK\")\u003c/li\u003e\r\n\u003cli\u003e\":version\" - The HTTP response version (e.g. \"HTTP/1.1\")\u003c/li\u003e\u003c/ul\u003e\r\n \u003c/li\u003e\r\n\u003cli\u003eAll header names must be lowercase.\u003c/li\u003e\r\n\u003cli\u003eThe Connection, Keep-Alive, Proxy-Connection, and Transfer-Encoding headers are not valid and MUST not be sent.\u003c/li\u003e\r\n\u003cli\u003eResponses MAY be accompanied by a Content-Length header for advisory purposes. (e.g. for UI progress meters)\u003c/li\u003e\r\n\u003cli\u003eIf\r\n a client receives a response where the sum of the data frame payload \r\nlengths does not equal the size of the Content-Length header, the client\r\n MUST ignore the content length header.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eIf\r\n a client receives a SYN_REPLY without a status or without a version \r\nheader, the client must reply with a RST_STREAM frame indicating a \r\nPROTOCOL ERROR.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-3.2.3-Authentication\" /\u003e3.2.3 Authentication\u003c/h3\u003e\r\n\u003cp\u003eWhen\r\n a client sends a request to an origin server that requires \r\nauthentication, the server can reply with a \"401 Unauthorized\" response,\r\n and include a WWW-Authenticate challenge header that defines the \r\nauthentication scheme to be used. The client then retries the request \r\nwith an Authorization header appropriate to the specified authentication\r\n scheme.\u003c/p\u003e\r\n\u003cp\u003eThere are four options for \r\nproxy authentication, Basic, Digest, NTLM and Negotiate (SPNEGO). The \r\nfirst two options were defined in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2617\" rel\u003d\"nofollow\"\u003eRFC2617\u003c/a\u003e, and are stateless. The second two options were developed by Microsoft and specified in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC4559\" rel\u003d\"nofollow\"\u003eRFC4559\u003c/a\u003e, and are stateful; otherwise known as multi-round authentication, or connection authentication.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-3.2.3.1-Stateless-Authentication\" /\u003e3.2.3.1 Stateless Authentication\u003c/h4\u003e\r\n\u003cp\u003eStateless\r\n Authentication over SPDY is identical to how it is performed over HTTP.\r\n If multiple SPDY streams are concurrently sent to a single server, each\r\n will authenticate independently, similar to how two HTTP connections \r\nwould independently authenticate to a proxy server.\u003c/p\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-3.2.3.2-Stateful-Authentication\" /\u003e3.2.3.2 Stateful Authentication\u003c/h4\u003e\r\n\u003cp\u003eUnfortunately,\r\n the stateful authentication mechanisms were implemented and defined in a\r\n such a way that directly violates RFC2617 - they do not include a \r\n\"realm\" as part of the request. This is problematic in SPDY because it \r\nmakes it impossible for a client to disambiguate two concurrent server \r\nauthentication challenges.\u003c/p\u003e\r\n\u003cp\u003eTo deal with this case, SPDY servers using Stateful Authentication MUST implement one of two changes: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eServers\r\n can add a \"realm\u003d\u0026lt;desired realm\u0026gt;\" header so that the two \r\nauthentication requests can be disambiguated and run concurrently. \r\nUnfortunately, given how these mechanisms work, this is probably not \r\npractical.\u003c/li\u003e\r\n\u003cli\u003eUpon sending the first stateful challenge response, \r\nthe server MUST buffer and defer all further frames which are not part \r\nof completing the challenge until the challenge has completed. \r\nCompleting the authentication challenge may take multiple round trips. \r\nOnce the client receives a \"401 Authenticate\" response for a stateful \r\nauthentication type, it MUST stop sending new requests to the server \r\nuntil the authentication has completed by receiving a non-401 response \r\non at least one stream.\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-3.3-Server-Push-Transactions\" /\u003e3.3 Server Push Transactions\u003c/h2\u003e\r\n\u003cp\u003eSPDY\r\n enables a server to send multiple replies to a client for a single \r\nrequest. The rationale for this feature is that sometimes a server knows\r\n that it will need to send multiple resources in response to a single \r\nrequest. Without server push features, the client must first download \r\nthe primary resource, then discover the secondary resource(s), and \r\nrequest them. Pushing of resources avoids the round-trip delay, but also\r\n creates a potential race where a server can be pushing content which a \r\nuser-agent is in the process of requesting. The following mechanics \r\nattempt to prevent the race condition while enabling the performance \r\nbenefit.\u003c/p\u003e\r\n\u003cp\u003eBrowsers receiving a pushed response MUST validate that the server is authorized to push the URL using the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003ebrowser same-origin\u003c/a\u003e policy. For example, a SPDY connection to www.foo.com is generally not permitted to push a response for www.evil.com.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n the browser accepts a pushed response (e.g. it does not send a \r\nRST_STREAM), the browser MUST attempt to cache the pushed response in \r\nsame way that it would cache any other response. This means validating \r\nthe response headers and inserting into the cache.\u003c/p\u003e\r\n\u003cp\u003eBecause\r\n pushed responses have no request, they have no request headers \r\nassociated with them. At the framing layer, SPDY pushed streams contain \r\nan \"associated-stream-id\" which indicates the requested stream for which\r\n the pushed stream is related. The pushed stream inherits all of the \r\nheaders from the associated-stream-id with the exception of \":host\", \r\n\":scheme\", and \":path\", which are provided as part of the pushed \r\nresponse stream headers. The browser MUST store these inherited and \r\nimplied request headers with the cached resource.\u003c/p\u003e\r\n\u003cp\u003eImplementation\r\n note: With server push, it is theoretically possible for servers to \r\npush unreasonable amounts of content or resources to the user-agent. \r\nBrowsers MUST implement throttles to protect against unreasonable push \r\nattacks.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-3.3.1-Server-implementation\" /\u003e3.3.1 Server implementation\u003c/h3\u003e\r\n\u003cp\u003eWhen\r\n the server intends to push a resource to the user-agent, it opens a new\r\n stream by sending a unidirectional SYN_STREAM. The SYN_STREAM MUST \r\ninclude an Associated-To-Stream-ID, and MUST set the FLAG_UNIDIRECTIONAL\r\n flag. The SYN_STREAM MUST include headers for \":scheme\", \":host\", \r\n\":path\", which represent the URL for the resource being pushed. \r\nSubsequent headers may follow in HEADERS frames. The purpose of the \r\nassociation is so that the user-agent can differentiate which request \r\ninduced the pushed stream; without it, if the user-agent had two tabs \r\nopen to the same page, each pushing unique content under a fixed URL, \r\nthe user-agent would not be able to differentiate the requests.\u003c/p\u003e\r\n\u003cp\u003eThe\r\n Associated-To-Stream-ID must be the ID of an existing, open stream. The\r\n reason for this restriction is to have a clear endpoint for pushed \r\ncontent. If the user-agent requested a resource on stream 11, the server\r\n replies on stream 11. It can push any number of additional streams to \r\nthe client before sending a FLAG_FIN on stream 11. However, once the \r\noriginating stream is closed no further push streams may be associated \r\nwith it. The pushed streams do not need to be closed (FIN set) before \r\nthe originating stream is closed, they only need to be created before \r\nthe originating stream closes.\u003c/p\u003e\r\n\u003cp\u003eIt is illegal for a server to push a resource with the Associated-To-Stream-ID of 0.\u003c/p\u003e\r\n\u003cp\u003eTo\r\n minimize race conditions with the client, the SYN_STREAM for the pushed\r\n resources MUST be sent prior to sending any content which could allow \r\nthe client to discover the pushed resource and request it.\u003c/p\u003e\r\n\u003cp\u003eThe server MUST only push resources which would have been returned from a GET request.\u003c/p\u003e\r\n\u003cp\u003eNote:\r\n If the server does not have all of the Name/Value Response headers \r\navailable at the time it issues the HEADERS frame for the pushed \r\nresource, it may later use an additional HEADERS frame to augment the \r\nname/value pairs to be associated with the pushed stream. The subsequent\r\n HEADERS frame(s) must not contain a header for ':host', ':scheme', or \r\n':path' (e.g. the server can't change the identity of the resource to be\r\n pushed). The HEADERS frame must not contain duplicate headers with a \r\npreviously sent HEADERS frame. The server must send a HEADERS frame \r\nincluding the scheme/host/port headers before sending any data frames on\r\n the stream.\u003c/p\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-3.3.2-Client-implementation\" /\u003e3.3.2 Client implementation\u003c/h3\u003e\r\n\u003cp\u003eWhen fetching a resource the client has 3 possibilities: \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003ethe resource is not being pushed\u003c/li\u003e\r\n\u003cli\u003ethe resource is being pushed, but the data has not yet arrived\u003c/li\u003e\r\n\u003cli\u003ethe resource is being pushed, and the data has started to arrive\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eWhen\r\n a SYN_STREAM and HEADERS frame which contains an \r\nAssociated-To-Stream-ID is received, the client must not issue GET \r\nrequests for the resource in the pushed stream, and instead wait for the\r\n pushed stream to arrive.\u003c/p\u003e\r\n\u003cp\u003eIf a client receives a server push stream with stream-id 0, it MUST issue a session error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.1-Session-Error-Handling\" title\u003d\"Session Error Handling\"\u003eSection 2.4.1\u003c/a\u003e) with the status code PROTOCOL_ERROR.\u003c/p\u003e\r\n\u003cp\u003eWhen\r\n a client receives a SYN_STREAM from the server without a the ':host', \r\n':scheme', and ':path' headers in the Name/Value section, it MUST reply \r\nwith a RST_STREAM with error code HTTP_PROTOCOL_ERROR.\u003c/p\u003e\r\n\u003cp\u003eTo cancel individual server push streams, the client can issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with error code CANCEL. Upon receipt, the server MUST stop sending on this stream immediately (this is an Abrupt termination).\u003c/p\u003e\r\n\u003cp\u003eTo cancel all server push streams related to a request, the client may issue a stream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e)\r\n with error code CANCEL on the associated-stream-id. By cancelling that \r\nstream, the server MUST immediately stop sending frames for any streams \r\nwith in-association-to for the original stream.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n the server sends a HEADER frame containing duplicate headers with a \r\nprevious HEADERS frame for the same stream, the client must issue a \r\nstream error (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.4.2-Stream-Error-Handling\" title\u003d\"Stream Error Handling\"\u003eSection 2.4.2\u003c/a\u003e) with error code PROTOCOL ERROR.\u003c/p\u003e\r\n\u003cp\u003eIf\r\n the server sends a HEADERS frame after sending a data frame for the \r\nsame stream, the client MAY ignore the HEADERS frame. Ignoring the \r\nHEADERS frame after a data frame prevents handling of HTTP's trailing \r\nheaders \r\n(http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.40).\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-4.-Design-Rationale-and-Notes\" /\u003e4. Design Rationale and Notes\u003c/h1\u003e\r\n\u003cp\u003eAuthors'\r\n notes: The notes in this section have no bearing on the SPDY protocol \r\nas specified within this document, and none of these notes should be \r\nconsidered authoritative about how the protocol works. However, these \r\nnotes may prove useful in future debates about how to resolve protocol \r\nambiguities or how to evolve the protocol going forward. They may be \r\nremoved before the final draft.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.1-Separation-of-Framing-Layer-and-Application-Layer\" /\u003e4.1 Separation of Framing Layer and Application Layer\u003c/h2\u003e\r\n\u003cp\u003eReaders may note that this specification sometimes blends the framing layer (\u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#FramingLayer\" title\u003d\"SPDY Framing Layer\" rel\u003d\"nofollow\"\u003eSection 2\u003c/a\u003e) with requirements of a specific application - HTTP (\u003ca href\u003d\"http://dev.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-3.-HTTP-Layering-over-SPDY\" title\u003d\"HTTP Layering over SPDY\"\u003eSection 3\u003c/a\u003e).\r\n This is reflected in the request/response nature of the streams, the \r\ndefinition of the HEADERS and compression contexts which are very \r\nsimilar to HTTP, and other areas as well.\u003c/p\u003e\r\n\u003cp\u003eThis\r\n blending is intentional - the primary goal of this protocol is to \r\ncreate a low-latency protocol for use with HTTP. Isolating the two \r\nlayers is convenient for description of the protocol and how it relates \r\nto existing HTTP implementations. However, the ability to reuse the SPDY\r\n framing layer is a non goal.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.2-Error-handling---Framing-Layer\" /\u003e4.2 Error handling - Framing Layer\u003c/h2\u003e\r\n\u003cp\u003eError\r\n handling at the SPDY layer splits errors into two groups: Those that \r\naffect an individual SPDY stream, and those that do not.\u003c/p\u003e\r\n\u003cp\u003eWhen\r\n an error is confined to a single stream, but general framing is in \r\ntact, SPDY attempts to use the RST_STREAM as a mechanism to invalidate \r\nthe stream but move forward without aborting the connection altogether.\u003c/p\u003e\r\n\u003cp\u003eFor\r\n errors occuring outside of a single stream context, SPDY assumes the \r\nentire session is hosed. In this case, the endpoint detecting the error \r\nshould initiate a connection close.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.3-One-Connection-Per-Domain\" /\u003e4.3 One Connection Per Domain\u003c/h2\u003e\r\n\u003cp\u003eSPDY\r\n attempts to use fewer connections than other protocols have \r\ntraditionally used. The rationale for this behavior is because it is \r\nvery difficult to provide a consistent level of service (e.g. TCP \r\nslow-start), prioritization, or optimal compression when the client is \r\nconnecting to the server through multiple channels.\u003c/p\u003e\r\n\u003cp\u003eThrough\r\n lab measurements, we have seen consistent latency benefits by using \r\nfewer connections from the client. The overall number of packets sent by\r\n SPDY can be as much as 40% less than HTTP. Handling large numbers of \r\nconcurrent connections on the server also does become a scalability \r\nproblem, and SPDY reduces this load.\u003c/p\u003e\r\n\u003cp\u003eThe \r\nuse of multiple connections is not without benefit, however. Because \r\nSPDY multiplexes multiple, independent streams onto a single stream, it \r\ncreates a potential for head-of-line blocking problems at the transport \r\nlevel. In tests so far, the negative effects of head-of-line blocking \r\n(especially in the presence of packet loss) is outweighed by the \r\nbenefits of compression and prioritization.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.4-Fixed-vs-Variable-Length-Fields\" /\u003e4.4 Fixed vs Variable Length Fields\u003c/h2\u003e\r\n\u003cp\u003eSPDY\r\n favors use of fixed length 32bit fields in cases where smaller, \r\nvariable length encodings could have been used. To some, this seems like\r\n a tragic waste of bandwidth. SPDY choses the simple encoding for speed \r\nand simplicity.\u003c/p\u003e\r\n\u003cp\u003eThe goal of SPDY is to \r\nreduce latency on the network. The overhead of SPDY frames is generally \r\nquite low. Each data frame is only an 8 byte overhead for a 1452 byte \r\npayload (~0.6%). At the time of this writing, bandwidth is already \r\nplentiful, and there is a strong trend indicating that bandwidth will \r\ncontinue to increase. With an average worldwide bandwidth of 1Mbps, and \r\nassuming that a variable length encoding could reduce the overhead by \r\n50%, the latency saved by using a variable length encoding would be less\r\n than 100 nanoseconds. More interesting are the effects when the larger \r\nencodings force a packet boundary, in which case a round-trip could be \r\ninduced. However, by addressing other aspects of SPDY and TCP \r\ninteractions, we believe this is completely mitigated.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.5-Compression-Context-s-\" /\u003e4.5 Compression Context(s)\u003c/h2\u003e\r\n\u003cp\u003eWhen\r\n isolating the compression contexts used for communicating with multiple\r\n origins, we had a few choices to make. We could have maintained a map \r\n(or list) of compression contexts usable for each origin. The basic case\r\n is easy - each HEADERS frame would need to identify the context to use \r\nfor that frame. However, compression contexts are not cheap, so the \r\nlifecycle of each context would need to be bounded. For proxy servers, \r\nwhere we could churn through many contexts, this would be a concern. We \r\nconsidered using a static set of contexts, say 16 of them, which would \r\nbound the memory use. We also considered dynamic contexts, which could \r\nbe created on the fly, and would need to be subsequently destroyed. All \r\nof these are complicated, and ultimately we decided that such a \r\nmechanism creates too many problems to solve.\u003c/p\u003e\r\n\u003cp\u003eAlternatively,\r\n we've chosen the simple approach, which is to simply provide a flag for\r\n resetting the compression context. For the common case (no proxy), this\r\n fine because most requests are to the same origin and we never need to \r\nreset the context. For cases where we are using two different origins \r\nover a single SPDY session, we simply reset the compression state \r\nbetween each transition.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.6-Unidirectional-streams\" /\u003e4.6 Unidirectional streams\u003c/h2\u003e\r\n\u003cp\u003eMany\r\n readers notice that unidirectional streams are both a bit confusing in \r\nconcept and also somewhat redundant. If the recipient of a stream \r\ndoesn't wish to send data on a stream, it could simply send a SYN_REPLY \r\nwith the FLAG_FIN bit set. The FLAG_UNIDIRECTIONAL is, therefore, not \r\nnecessary.\u003c/p\u003e\r\n\u003cp\u003eIt is true that we don't need \r\nthe UNIDIRECTIONAL markings. It is added because it avoids the recipient\r\n of pushed streams from needing to send a set of empty frames (e.g. the \r\nSYN_STREAM w/ FLAG_FIN) which otherwise serve no purpose.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.7-Data-Compression\" /\u003e4.7 Data Compression\u003c/h2\u003e\r\n\u003cp\u003eGeneric\r\n compression of data portion of the streams (as opposed to compression \r\nof the headers) without knowing the content of the stream is redundant. \r\nThere is no value in compressing a stream which is already compressed. \r\nBecause of this, SPDY initially allowed data compression to be optional.\r\n We included it because study of existing websites shows that many sites\r\n are not using compression as they should, and users suffer because of \r\nit. We wanted a mechanism where, at the SPDY layer, site administrators \r\ncould simply force compression - it is better to compress twice than to \r\nnot compress.\u003c/p\u003e\r\n\u003cp\u003eOverall, however, with this\r\n feature being optional and sometimes redundant, it was unclear if it \r\nwas useful at all. We removed it from the specification.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-4.8-Server-Push\" /\u003e4.8 Server Push\u003c/h2\u003e\r\n\u003cp\u003eA\r\n subtle but important point is that server push streams must be declared\r\n before the associated stream is closed. The reason for this is so that \r\nproxies have a lifetime for which they can discard information about \r\nprevious streams. If a pushed stream could associate itself with an \r\nalready-closed stream, then endpoints would not have a specific \r\nlifecycle for when they could disavow knowledge of the streams which \r\nwent before.\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-5.-Security-Considerations\" /\u003e5. Security Considerations\u003c/h1\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-5.1-Use-of-Same-origin-constraints\" /\u003e5.1 Use of Same-origin constraints\u003c/h2\u003e\r\n\u003cp\u003eThis specification uses the \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC6454\" rel\u003d\"nofollow\"\u003esame-origin policy\u003c/a\u003e in all cases where verification of content is required.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-5.2-HTTP-Headers-and-SPDY-Headers\" /\u003e5.2 HTTP Headers and SPDY Headers\u003c/h2\u003e\r\n\u003cp\u003eAt\r\n the application level, HTTP uses name/value pairs in its headers. \r\nBecause SPDY merges the existing HTTP headers with SPDY headers, there \r\nis a possibility that some HTTP applications already use a particular \r\nheader name. To avoid any conflicts, all headers introduced for layering\r\n HTTP over SPDY are prefixed with \":\". \":\" is not a valid sequence in \r\nHTTP header naming, preventing any possible conflict.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-5.3-Cross-Protocol-Attacks\" /\u003e5.3 Cross-Protocol Attacks\u003c/h2\u003e\r\n\u003cp\u003eBy\r\n utilizing TLS, we believe that SPDY introduces no new cross-protocol \r\nattacks. TLS encrypts the contents of all transmission (except the \r\nhandshake itself), making it difficult for attackers to control the data\r\n which could be used in a cross-protocol attack.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-5.4-Server-Push-Implicit-Headers\" /\u003e5.4 Server Push Implicit Headers\u003c/h2\u003e\r\n\u003cp\u003ePushed\r\n resources do not have an associated request. In order for existing HTTP\r\n cache control validations (such as the Vary header) to work, however, \r\nall cached resources must have a set of request headers. For this \r\nreason, browsers MUST be careful to inherit request headers from the \r\nassociated stream for the push. This includes the 'Cookie' header.\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-6.-Privacy-Considerations\" /\u003e6. Privacy Considerations\u003c/h1\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-6.1-Long-Lived-Connections\" /\u003e6.1 Long Lived Connections\u003c/h2\u003e\r\n\u003cp\u003eSPDY\r\n aims to keep connections open longer between clients and servers in \r\norder to reduce the latency when a user makes a request. The maintenance\r\n of these connections over time could be used to expose private \r\ninformation. For example, a user using a browser hours after the \r\nprevious user stopped using that browser may be able to learn about what\r\n the previous user was doing. This is a problem with HTTP in its current\r\n form as well, however the short lived connections make it less of a \r\nrisk.\u003c/p\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-6.2-SETTINGS-frame\" /\u003e6.2 SETTINGS frame\u003c/h2\u003e\r\n\u003cp\u003eThe\r\n SPDY SETTINGS frame allows servers to store out-of-band transmitted \r\ninformation about the communication between client and server on the \r\nclient. Although this is intended only to be used to reduce latency, \r\nrenegade servers could use it as a mechanism to store identifying \r\ninformation about the client in future requests.\u003c/p\u003e\r\n\u003cp\u003eClients\r\n implementing privacy modes, such as Google Chrome's \"incognito mode\", \r\nmay wish to disable client-persisted SETTINGS storage.\u003c/p\u003e\r\n\u003cp\u003eClients MUST clear persisted SETTINGS information when clearing the cookies.\u003c/p\u003e\r\n\u003cp\u003eTODO: Put range maximums on each type of setting to limit inappropriate uses.\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-7.-Incompatibilities-with-SPDY-draft-2\" /\u003e7. Incompatibilities with SPDY draft #2\u003c/h1\u003e\r\n\u003cp\u003eHere is a list of the major changes between this draft and draft #2. \u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eAddition of flow control\u003c/li\u003e\r\n\u003cli\u003eIncreased 16 bit length fields in SYN_STREAM and SYN_REPLY to 32 bits.\u003c/li\u003e\r\n\u003cli\u003eChanged definition of compression for DATA frames\u003c/li\u003e\r\n\u003cli\u003eUpdated compression dictionary\u003c/li\u003e\r\n\u003cli\u003eFixed off-by-one on the compression dictionary for headers\u003c/li\u003e\r\n\u003cli\u003eIncreased priority field from 2bits to 3bits.\u003c/li\u003e\r\n\u003cli\u003eRemoved NOOP frame\u003c/li\u003e\r\n\u003cli\u003eSplit the request \"url\" into \"scheme\", \"host\", and \"path\"\u003c/li\u003e\r\n\u003cli\u003eAdded the requirement that POSTs contain content-length.\u003c/li\u003e\r\n\u003cli\u003eRemoved wasted 16bits of unused space from the end of the SYN_REPLY and HEADERS frames.\u003c/li\u003e\r\n\u003cli\u003eFixed bug: Priorities were described backward (0 was lowest instead of highest).\u003c/li\u003e\r\n\u003cli\u003eFixed bug: Name/Value header counts were duplicated in both the Name Value header block and also the containing frame.\u003c/li\u003e\u003cli\u003eFixed endianness issues with SETTINGS ids (which were little endian). Now everything is big endian.\u003c/li\u003e\u003cli\u003eHeader values can now be empty.\u003c/li\u003e\u003c/ul\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-8.-Requirements-Notation\" /\u003e8. Requirements Notation\u003c/h1\u003e\r\n\u003cp\u003eThe\r\n key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\", \r\n\"SHOULD\", \"SHOULD NOT\", \"RECOMMENDED\", \"MAY\", and \"OPTIONAL\" in this \r\ndocument are to be interpreted as described in \u003ca href\u003d\"http://mbelshe.github.com/SPDY-Specification/draft-mbelshe-spdy-00.xml#RFC2119\" rel\u003d\"nofollow\"\u003eRFC 2119\u003c/a\u003e.\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-9.-Acknowledgements\" /\u003e9. Acknowledgements\u003c/h1\u003e\r\n\u003cp\u003eMany\r\n individuals have contributed to the design and evolution of SPDY: Adam \r\nLangley, Wan-Teh Chang, Jim Morrison, Mark Nottingham, Alyssa Wilk, \r\nCostin Manolache, William Chan, Vitaliy Lvin, Joe Chan, Adam Barth, Ryan\r\n Hamilton, Gavin Peters, Kent Alstad, Kevin Lindsay, Paul Amer, Fan \r\nYang, Jonathan Leighton\u003c/p\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-10.-Normative-References\" /\u003e10. Normative References\u003c/h1\u003e\r\n\u003ctable\u003e \r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd\u003e\u003cb\u003e[TLSNPN]\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd\u003eLangley, A., “\u003ca href\u003d\"http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\" rel\u003d\"nofollow\"\u003eTLS Next Protocol Negotiation\u003c/a\u003e”, \u0026lt;\u003ca href\u003d\"http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\" rel\u003d\"nofollow\"\u003ehttp://tools.ietf.org/html/draft-agl-tls-nextprotoneg-01\u003c/a\u003e\u0026gt;.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n \r\n\u003ctr\u003e\r\n\u003ctd\u003e\u003cb\u003e[ASCII]\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd\u003e“US-ASCII.\r\n Coded Character Set - 7-Bit American Standard Code for Information \r\nInterchange. Standard ANSI X3.4-1986, ANSI, 1986.”.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n \r\n\u003ctr\u003e\r\n\u003ctd\u003e\u003cb\u003e[UDELCOMPRESSION]\u003c/b\u003e\u003c/td\u003e\r\n\u003ctd\u003eYang, F., Amer, P., and J. Leighton, “\u003ca href\u003d\"http://www.eecis.udel.edu/%7Eamer/PEL/poc/pdf/SPDY-Fan.pdf\" rel\u003d\"nofollow\"\u003eA Methodology to Derive SPDY’s Initial Dictionary for Zlib Compression\u003c/a\u003e”, \u0026lt;\u003ca href\u003d\"http://www.eecis.udel.edu/%7Eamer/PEL/poc/pdf/SPDY-Fan.pdf\" rel\u003d\"nofollow\"\u003ehttp://www.eecis.udel.edu/~amer/PEL/poc/pdf/SPDY-Fan.pdf\u003c/a\u003e\u0026gt;.\u003c/td\u003e\r\n\u003c/tr\u003e\r\n \u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003chr /\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-11.-Errata\" /\u003e11. Errata\u003c/h1\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003eSection 2.6.6 originally listed INTERNAL_ERROR as status code 11.\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003chr /\u003e\r\n\u003cdiv\u003e\r\n\u003ch1\u003e\u003ca name\u003d\"TOC-Authors-Addresses\" /\u003eAuthors' Addresses\u003c/h1\u003e\r\n\u003caddress\u003e\u003cspan\u003eMike Belshe \u003c/span\u003e\u003cspan\u003eTwist \u003c/span\u003e\u003cspan\u003eEMail: \u003ca href\u003d\"mailto:mbelshe@chromium.org\"\u003e\u003cspan\u003embelshe@chromium.org\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/address\u003e\r\n\u003caddress\u003e\u003cspan\u003eRoberto Peon \u003c/span\u003e\u003cspan\u003eGoogle, Inc \u003c/span\u003e\u003cspan\u003eEMail: \u003ca href\u003d\"mailto:fenix@google.com\"\u003e\u003cspan\u003efenix@google.com\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/address\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/385872135698932510"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/spdy/spdy-protocol/spdy-protocol-draft3"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1689100172383001656"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1689100172383001656"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1689100172383001656"}],"author":[{"name":{"$t":"William Chan"},"email":{"$t":"willchan@chromium.org"}}],"sites$pageName":{"$t":"spdy-protocol-draft3"},"sites$revision":{"$t":"13"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5579911288443845098"},"published":{"$t":"2014-01-14T00:27:52.663Z"},"updated":{"$t":"2014-01-14T00:33:44.657Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2014-01-14T00:33:42.867Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Surfaces"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"text-align:left;line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-family:Arial;font-size:19px;font-weight:bold;white-space:pre-wrap;line-height:1.15\"\u003eGoals\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSurfaces are a concept to allow graphical \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eembedding\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e of \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eheterogeneous\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003euntrusting\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e clients \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eefficiently\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e into one scene.  \u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.5;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eembedding\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e - the core concept of a surface is that it may contain references to surfaces from the same client or different clients\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.5;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eheterogeneous\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e - rendering to a surface does not require that a client use a specific library or toolkit, only that it be able to speak the surface protocol\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.5;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003euntrusting\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e - a client does not have to trust its embedding or embedded clients in order to render into a surface.  Having access to a surface from another client does not provide any access to that surface’s contents.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.5;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eefficiently\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e - rendering to a surface should have minimal overhead compared to rendering directly to the native screen and should be equally efficient regardless of the embedding depth.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eUse cases\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIn Chromium, we can use surfaces for many of the embedding cases we have today:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eembedding a blink-rendered tab in the browser’s UI\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eembedding a plugin or video within a page\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eembedding an iframe rendered from one process into an iframe rendered in a different process\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eConcepts\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSurface\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is a fixed size rectangle that can be rendered into by submitting frames.  A client can create a surface by asking the SurfaceManager to construct one for a client (possibly itself) to render into.  A Surface can be identified by two IDs generated by the SurfaceManager - one for identifying the surface when issuing frames to render to the surface, one to identify the surface when rendering from it to embed.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eFrame\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is a series of quads to draw, some of which may reference other surfaces.  A frame also contains a set of resources and associated synchronization points.  Here’s a (rough) outline of the structure of a frame:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eList of prerequisite sequence numbers for the frame\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eList of resources with associated synchronization points\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eList of passes, each of which contains\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTransform of the pass\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDamage and output rects\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eList of quads within the pass, each of which has\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTransform / rect / clip state / opacity / blend mode / etc (may be shared with other quads)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eMaterial - maybe solid color, texture, surface, etc\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eMaterial-specific properties such as color, texture ID, surface ID\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe act of submitting a frame generates an implicit sequence number that can be used to synchronize presentation with other frames, potentially submitted by other clients.  A surface identifier + sequence number tuple unique identifies a frame for all clients of an instance of the service (and there will typically only be one surface service in the system).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eDisplay\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e is a physical display (when Chromium is the operating system) or a native OS window object (when Chromium is running inside another operating system).  The surface service provides a surface for each display for a designated client to issue frames to.  In the case of Chromium running on windows, for example, the surface service would generate a surface identifier for each top-level HWND and provide them to the browser UI code to render into.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOf particular note is that on Mac we can construct a display wrapping an IOSurface for each tab and let CoreAnimation composite the tabs with the browser UI.  This does not provide the bandwidth benefits of ÜberCompositor but it does allow everything outside of the browser process to use the same presentation path as platforms using Aura/ÜberCompositor and reduce a lot of platform-specific complexity in our code.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eProcessing model\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eFor clients:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhenever a client wants to update the rendering of a surface it owns, it generates a new frame and submits it to the SurfaceManager.  This frame may contain quads that references surfaces being embedded by this client.  A client does not have to issue a new frame whenever a surface it embeds updates its rendering.  Issuing a frame also transfers ownership of resources (GL textures, software shared memory buffers).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhenever a client wants to start embedding another client, it first generates an appropriately sized surface through the SurfaceManager and then sends it to the client.  The embedding client can start immediately issuing frames referencing the new surface or it may wait to receive an acknowledgement from the embedded client that the surface is ready, depending on the desired application semantics.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eResizing is analogous to creating a new surface.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eFor the service:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhenever the manager receives a new frame, it performs some sanity checks on the frame (i.e. making sure it only references frames that the client should be referencing) and then saves it in the surface’s potential frame list along.  Whenever this frame’s prerequisites are satisfied, it is moved into the eligible frame list for the surface.  Only one frame can be rendered for a given surface at a time, but a client is allowed to pipeline multiple frames.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhenever a display is ready for a new frame and something has changed, the service aggregates frames from the surfaces that contribute to that display and then renders them.  The aggregation algorithm is simple:\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eStart with the most recent eligible frame issued to the surface associated with the display\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIterate through the quads in the frame in draw order, keeping track of the current clip and transform\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:lower-alpha;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf the quad is not a reference to another surface, draw it\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:lower-alpha;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf the quad is a reference to another surface, find the most recent eligible frame issued to the referenced surface\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003col style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:lower-roman;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf there is no such frame, or if this surface has already been visited in this aggregation (i.e. there’s a cycle) skip the surface quad\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:lower-roman;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOtherwise, recursively repeat this algorithm from step 2\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/ol\u003e\u003c/ol\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eWhen the service knows that it will never render from a given frame again - for instance if it has started rendering a newer frame for a given surface or if the embedding client has told the manager that it wants to destroy a surface - the service sends an acknowledgement to the client with a set of resources to return to the client along with associated synchronization points.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSurfaceService structure\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cimg height\u003d\"431px;\" src\u003d\"https://docs.google.com/a/chromium.org/drawings/d/s_yolhxJiIsHvNqY0pwkVFw/image?w\u003d624\u0026amp;h\u003d431\u0026amp;rev\u003d3\u0026amp;ac\u003d1\" style\u003d\"border:0px solid transparent\" width\u003d\"624px;\" /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSurfaceManager\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e keeps track of all surfaces created in the system.  For each surface, it keeps track of:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe client that created the surface and will be embedding (rendering from) the surface\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe client that will be rendering into the surface (may be the same as the creator)\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eList of submitted frames for the given surface\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eResourceProvider\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e keeps track of resources that the service has ownership of and how to return ownership to clients.  For GL textures, for instance, this means managing mailboxes.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eDisplayManager\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e keeps track of all displays that the surface service is responsible for rendering into.  For each display, the DisplayManager owns a surface used to render into the display as well as some state for hit testing against surfaces and determining which surfaces contributed to the display’s last produced frame.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThere is only one instance of each of the Manager types in an instance of the service.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSurfaceAggregator\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e implements the aggregation algorithm and knows how to submit an aggregated frame to a renderer.  Aggregators are (nearly) stateless and can be created whenever necessary.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eA \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eRenderer\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e translates an aggregated frame into draw commands appropriate for a given display.  In GPU rendering mode, this means GL draw calls and a swap into the display.  In software rendering mode, this means skia calls into the appropriate SkCanvas.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:19px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSynchronization\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eResource synchronization is the same as it is with \u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;vertical-align:baseline;white-space:pre-wrap\"\u003eÜ\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eberCompositor, with the slight simplification that the pipeline depth is not influenced by the nesting level of the embedding.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eClients can optionally synchronize frames with each other using the prerequisite / postrequisite synchronization points.  This has to be done with care but can be useful to do things like prevent resize guttering.  99% of the use cases in Chromium will not require any explicit synchronization between different surfaces - in nearly all cases it’s perfectly fine (and desirable) to let clients render independently of each other.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHere’s an example of a possible gutter prevention algorithm.  Assume that client Alice is embedding client Bob and wants to resize its surface for Bob from 100x100 to 200x200.  If Bob responds fast enough to Alice’s resize message, Alice wants to make sure that Bob shows up at 200x200 in the same frame as Alice’s decorations.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eStart conditions\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice is embedding Bob.  Alice owns a 100x100 surface that Bob is rendering into.  Alice and Bob both have pending frames referencing the 100x100 surface.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSequence for Alice\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice decides to resize Bob to 200x200 and change decorations that Alice is rendering. \u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice requests a new 200x200 surface from the SurfaceManager\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice sends Bob a resize request and a handle to the new 200x200 surface\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice starts a timeout\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf Bob responds to the resize message before the timeout:\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice issues the first frame referencing the 200x200 surface with a prerequisite sequence number that it got from Bob\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:circle;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf Bob doesn’t respond before the timeout:\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:square;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice issues a frame referencing the 100x100 surface and appropriate quads to stretch or gutter as appropriate\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eRegardless of when the resize response comes in, Alice issues a destroy call for the 100x100 surface to the SurfaceManager after starting to issues frames referencing the 200x200 surface.\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eSequence for Bob\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cul style\u003d\"margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBob receives a resize message with the new surface identifier\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBob issues a new frame appropriate for a 200x200 surface which generates a sequence number for the frame\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:disc;font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBob sends a resize response to Alice with this sequence number\u003c/span\u003e\u003c/p\u003e\u003c/li\u003e\u003c/ul\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eEnd conditions\u003c/span\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e:\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAlice and Bob are referencing a 200x200 surface\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe SurfaceManager knows that the 100x100 surface can be destroyed as soon as the service no longer needs it.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIf Bob is slow to respond, Alice may stall or submit one or more frames that gutter.  However if Bob responds fast enough the service can guarantee using the sequence numbers that the new frame from Bob and the new decorations from Alice show up on screen at the same time. \u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9026127630943746559"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/chromium-graphics/surfaces"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5579911288443845098"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5579911288443845098"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5579911288443845098"}],"author":[{"name":{"$t":"James Robinson"},"email":{"$t":"jamesr@chromium.org"}}],"sites$pageName":{"$t":"surfaces"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"WCl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7950208076219910713"},"published":{"$t":"2013-01-25T21:09:20.514Z"},"updated":{"$t":"2014-01-13T20:42:05.956Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-01-28T14:25:06.343Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"TPM Usage"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Modes-of-Operation\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eModes of Operation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-TPM-Ownership-and-Restrictions\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eTPM Ownership and Restrictions\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Rollback-Prevention\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eRollback Prevention\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Protecting-User-Data-Encryption-Keys\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eProtecting User Data Encryption Keys\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Protecting-Certain-User-RSA-Keys\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eProtecting Certain User RSA Keys\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Tamper-Evident-Installation-Attributes\"\u003e\u003cstrong\u003e7 \u003c/strong\u003eTamper-Evident Installation Attributes\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Stateful-Partition-Encryption\"\u003e\u003cstrong\u003e8 \u003c/strong\u003eStateful Partition Encryption\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Attesting-TPM-Protected-Keys\"\u003e\u003cstrong\u003e9 \u003c/strong\u003eAttesting TPM-Protected Keys\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Attesting-Device-Mode\"\u003e\u003cstrong\u003e10 \u003c/strong\u003eAttesting Device Mode\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Chrome-OS-Specific-TPM-Configuration\"\u003e\u003cstrong\u003e11 \u003c/strong\u003eChrome OS-Specific TPM Configuration\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\r\n\u003cp\u003eThis document describes the usage of a Trusted Platform Module (TPM) in Chrome devices (Chromebook or other form factors), including firmware, operating system, and applications. It assumes some knowledge of Chrome OS concepts as well as TPM functions. It may be of interest to Chromium OS developers who want to use the TPM and to users who wish to understand the usage of the TPM in Chrome OS.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eChrome OS uses the TPM for these tasks:\u003c/p\u003e\r\n\r\n\r\n\u003cul\u003e\r\n\u003cli\u003ePreventing software and firmware version rollback\u003c/li\u003e\r\n\u003cli\u003eMaintaining information to detect transitions between normal and developer modes\u003c/li\u003e\r\n\u003cli\u003eProtecting user data encryption keys\u003c/li\u003e\r\n\u003cli\u003eProtecting certain user RSA keys (‘hardware-backed’ certificates)\u003c/li\u003e\r\n\u003cli\u003eProviding tamper evidence for installation attributes\u003c/li\u003e\r\n\u003cli\u003eProtecting stateful partition encryption keys\u003c/li\u003e\r\n\u003cli\u003eAttesting TPM-protected keys\u003c/li\u003e\r\n\u003cli\u003eAttesting device mode\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\r\n\u003cp\u003eThe TPM is not directly available outside of Chrome OS for any purpose; that is, no remote computer has access to the TPM.\u003c/p\u003e\r\n\r\n\r\n\r\n\r\n\u003cp\u003eChrome OS does not use the TPM for the following:\u003c/p\u003e\r\n\r\n\u003cul\u003e\r\n\u003cli\u003eTrusted boot - the TPM is not used as part of the Chrome OS verified boot solution.\u003c/li\u003e\r\n\u003cli\u003eHardware-strength platform configuration reporting. See \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/tpm-usage#TOC-Attesting-Device-Mode\"\u003eAttesting Device Mode\u003c/a\u003e for more details.\u003c/li\u003e\r\n\u003cli\u003eWhole-disk encryption or similar. In particular, the TPM is not used to unwrap an encryption key during the boot process.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\r\n\u003cp\u003eThe rest of this document first discusses the four different modes of operation of Chrome devices; then it describes how Chrome OS controls TPM ownership; and finally it presents each area of TPM usage in detail.\u003c/p\u003e\r\n\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Modes-of-Operation\" /\u003eModes of Operation\u003c/h2\u003e\r\n\r\n\u003cp\u003eA Chrome device can be booted in four different modes, corresponding to the settings of two switches (physical or virtual) at power on. They are the developer switch and the recovery switch. They may be physically present on the device, or they may be virtual, in which case they are triggered by certain key presses at power on. When both switches are off, the boot is called normal mode boot. When the developer switch is on, it is called developer mode boot. When the recovery switch is on, it is called recovery mode boot (and normal-recovery or developer-recovery when there is a need to distinguish them).\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eThese modes give users a choice between a high degree of security or complete control over the device. In normal mode, the device is running a Google-provided copy of Chrome OS, which cannot be altered (assuming the hardware has not been tampered with). In developer mode, users can run a modified copy of Chromium OS (or any other supported operating system), though without some of the Chrome OS security defenses. The recovery modes allow for installation of Chrome OS or Chromium OS from recovery media.\u003c/p\u003e\r\n\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-TPM-Ownership-and-Restrictions\" /\u003eTPM Ownership and Restrictions\u003c/h2\u003e\r\n\r\n\u003cp\u003eMost of the TPM functionality becomes available after a TPM owner is established. In normal mode, Chrome OS attempts to establish a TPM owner with a random password, which is generated only after the owner of the Chrome device starts using it. When the owner password is created, there is a period of time in which the user can find out what it is and write it down. After this period, the password is destroyed. However, knowledge of the owner password is not necessary at any point in Chrome OS.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eUnder certain conditions, the TPM owner will be cleared, rendering keys currently protected by the TPM useless (and therefore the data protected by those keys unrecoverable). These conditions are as follows:\u003c/p\u003e\r\n\r\n\u003cul\u003e\r\n\u003cli\u003eOn the first power-on after switching to developer mode, the TPM is cleared by the firmware before the OS kernel begins booting.\u003c/li\u003e\r\n\u003cli\u003eOn the first power-on after switching to normal mode, the TPM is also cleared by the firmware before the OS kernel begins booting.\u003c/li\u003e\r\n\u003cli\u003eDuring a recovery mode boot in normal mode, a Chrome OS recovery image will clear the TPM before the device is rebooted.\u003c/li\u003e\r\n\u003cli\u003eSome Chrome devices allow the system (or, if in developer mode, the user) to explicitly request that the TPM owner be cleared on the next reboot.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\r\n\u003cp\u003eWhen a non-Chrome OS image is booted in developer mode, it is up to that user-installed OS to decide whether or not to take ownership, or do anything at all with the TPM. The user-installed system, for example, may create additional TPM NVRAM spaces other than those that Chrome OS creates (e.g., see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/tpm-usage#TOC-Rollback-Prevention\"\u003eRollback Prevention\u003c/a\u003e below).\u003c/p\u003e\r\n \r\n\r\n\r\n\u003cp\u003eNote the following developer mode restrictions on the TPM:\u003c/p\u003e\r\n\r\n\r\n\u003cul\u003e\r\n\u003cli\u003eThe TPM physical presence command is disabled by the read-write firmware on every boot. This means that physical presence cannot be asserted even by a custom OS.\u003c/li\u003e\r\n\u003cli\u003eThe NVRAM firmware space (see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/tpm-usage#TOC-Rollback-Prevention\"\u003eRollback Prevention\u003c/a\u003e below) cannot be removed.\u003c/li\u003e\r\n\u003cli\u003eThe NVRAM kernel space (see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/tpm-usage#TOC-Rollback-Prevention\"\u003eRollback Prevention\u003c/a\u003e below) can be removed, but doing so will result in the firmware forcing recovery mode at the next boot.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\r\n\u003cp\u003eIn the event that the NVRAM kernel space is removed, the device will only boot a Google-provided recovery image, which will try to reconstruct that space. Chrome OS recovery will aggressively destroy other spaces as needed to make room.\r\n\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Rollback-Prevention\" /\u003eRollback Prevention\u003c/h2\u003e\r\n\r\n\u003cp\u003eThe normal boot process of a Chrome device follows a chain of trust, in the following order:\u003c/p\u003e\r\n\r\n\u003col\u003e\r\n\u003cli\u003eRead-only section of firmware (set during factory installation and unchangeable in software)\u003c/li\u003e\r\n\u003cli\u003eUpgradable section of firmware (called read-write firmware)\u003c/li\u003e\r\n\u003cli\u003eKernel\u003c/li\u003e\r\n\u003cli\u003ePrograms and services that comprise the operating system\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\r\n\r\n\u003cp\u003eEach link in the chain is responsible for verifying that the next link has not been tampered with before yielding control to it.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eRead-write firmware and kernel can be updated, either manually (through a “recovery” process) or automatically. For security, the automatic update process does not allow updating to versions of the software that are older than the current one. This prevents “remote rollback attacks,” in which a remote attacker replaces newer software, through a hard to exploit vulnerability, with older software, with a well-known and easy to exploit vulnerability.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eTo prevent remote rollback attacks, Chrome devices reserve two small NVRAM spaces in the TPM to store version numbers and other information. These NVRAM spaces are called “firmware space” and “kernel space.” They are created during factory initialization and are never removed. (The kernel space can be removed in developer mode, but the firmware space cannot. Also note that a Chrome OS recovery image will try to recreate the kernel space, possibly removing other spaces to make room.)\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eThe firmware space contains the read-write firmware version number (among other things). It is created with permission TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, and is locked by setting the TPM bGlobalLock bit. On a normal boot, this space is locked by the read-only firmware, possibly after updating it to reflect the version of the verified read-write firmware installed. As mentioned, this update may only replace the current version number with a larger one.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eThe kernel space contains the kernel version number. It is created with permission TPM_NV_PER_PPWRITE. On a normal boot it is locked by turning off and locking physical presence in the read-write firmware. As in the case of the firmware space, the read-write firmware will update this number to the version number of the current kernel.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eOn a recovery boot (either in normal or developer mode), neither the firmware nor the kernel space is locked. Therefore the recovery image can bypass the anti-rollback mechanism. Bypassing the anti-rollback mechanism is allowed because there are legitimate cases in which it is desirable to install older versions of the system, as long as this rollback does not happen without the knowledge of the user.\u003c/p\u003e\r\n\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Protecting-User-Data-Encryption-Keys\" /\u003eProtecting User Data Encryption Keys\u003c/h2\u003e\r\n\r\n\u003cp\u003eUser data in Chrome OS is encrypted when stored on the disk using the eCryptfs stacked filesystem. When a user logs in for the first time, two random 128-bit AES keys are generated. One key is used by eCryptfs to encrypt file names, and the other is used to encrypt file content. These keys are managed locally; they are not escrowed outside of the Chrome device. This allows users to log in and access their data while offline and also means that the keys never need to leave the device. However, this feature also necessitates a strong method of protecting these keys from disclosure as they are stored in a persistent file on disk.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eChrome OS uses the TPM to make parallelized attacks and password brute-forcing difficult. One feature and one characteristic of the TPM are exploited here. First, the TPM provides secure key storage for RSA keys. This means that the private key only exists in plain text while it resides on the TPM itself--it can only be stored outside of the TPM in encrypted form. This feature makes parallelizing difficult: decrypt operations involving that key must happen on the TPM itself (unless a vulnerability exists whereby the attacker can obtain the plain-text private key of a TPM-wrapped RSA key). Second, the TPM is a relatively slow device. Private key \r\noperations can take over half a second to complete; this provides a level of brute-force protection by effectively throttling the rate at which guesses can be made.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eTo protect the user keys, Chrome OS creates a system-wide RSA key wrapped by the TPM’s Storage Root Key (SRK) on first boot. When storing a particular user’s AES keyset, Chrome OS encrypts the keyset using a random symmetric key. That symmetric key is encrypted using the system-wide RSA key. To tie the decryption to a user secret, 128 bits of this encrypted blob are encrypted a second time using a key derived from the user’s login password. Since this step is done without padding, any decryption must blindly decrypt those 128 bits and then decrypt the entire blob on the TPM before knowing if the decryption process (and therefore the password) was correct. Using this method (over per-user TPM keys requiring authentication) has the benefit of avoiding the TPM’s dictionary attack defense, which is overly aggressive for use during user login.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eThere are two important implications to the use of the TPM to protect user data:\u003c/p\u003e\r\n\r\n\u003cul\u003e\r\n\u003cli\u003eIf the TPM is cleared, user data protected by it cannot be recovered. In this case, Chrome OS removes user data.\u003c/li\u003e\r\n\u003cli\u003eIf the TPM is somehow disabled or faults, user data cannot be accessed. Chrome OS will fail logins for existing users until the TPM is enabled.\u003c/li\u003e\r\n\u003c/ul\u003e\r\n\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Protecting-Certain-User-RSA-Keys\" /\u003eProtecting Certain User RSA Keys\u003c/h2\u003e\r\n\r\n\u003cp\u003eChrome OS implements TPM-backed cryptographic services via the Chaps PKCS #11 component. (More information about Chaps can be found in the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/chaps-technical-design\"\u003eChaps Technical Design\u003c/a\u003e.) RSA private keys generated or imported into a Chaps PKCS #11 token with a modulus size supported by the TPM (typically up to 2048 bits) will be wrapped by the TPM Storage Root Key (SRK). Each user account on the device has a distinct token. A user can import a certificate and private key into his TPM-backed token by using the ‘Import and Bind’ operation available in Chrome’s certificate manager. Also, any keys generated using the Webkit ‘keygen’ tag will use the TPM-backed token by default.\u003c/p\u003e\r\n\r\n\r\n\u003cp\u003eRSA private keys that are not supported by the TPM and all other PKCS #11 data (certificates, public keys, data objects, TPM-encrypted key blobs, etc.) are encrypted with a symmetric key and stored in /home/chronos/user/.chaps. This symmetric key is itself encrypted using a TPM-backed key which requires a value partially derived from the user password for authorization. Thus, a user’s Chaps token can only be decrypted if both the TPM and the user password are available.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Tamper-Evident-Installation-Attributes\" /\u003eTamper-Evident Installation Attributes\u003c/h2\u003e\r\n\r\n\u003cp\u003eThe first time a device is used, a set of installation attributes is stored on the device and remains tamper-evident for the remainder of the install (i.e., until the device mode changes). If a device has been enterprise enrolled, as evidenced by a ribbon with text like “This device is owned by yourcompany.com,” then the installation attributes correspond to this enrollment. If not, the set of attributes is empty. Either way, the tamper-evidence for the set of attributes is implemented by computing a salted hash of the attributes and storing the random salt and the hash in TPM NVRAM with TPM_NV_PER_WRITE_DEFINE permissions (i.e. read-only until destroyed by the TPM owner). The hash can then be verified at any time to ensure the attributes have not been modified. This tamper-evident container is referred to as the “lockbox.”\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Stateful-Partition-Encryption\" /\u003eStateful Partition Encryption\u003c/h2\u003e\r\n\r\n\u003cp\u003eSome parts (e.g., /var, /home/chronos) of the stateful partition are encrypted using dm-crypt. The encryption key is randomly chosen via the TPM’s RNG on first boot and is encrypted by a TPM-held “system key” (read from TPM NVRAM during startup). This system key is actually the random salt used for hashing installation attributes.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Attesting-TPM-Protected-Keys\" /\u003eAttesting TPM-Protected Keys\u003c/h2\u003e\r\n\r\n\u003cp\u003eIf an RSA private key has been generated in the TPM and has always been non-migratable, then the key may be certified by a key that has been verified as an Attestation Identity Key (AIK). No key, including any AIK, is certified unless the user or device-owner has consented to remote attestation of his or her device. A certified key credential gives very strong assurance that the key is protected by a Chrome Device TPM.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Attesting-Device-Mode\" /\u003eAttesting Device Mode\u003c/h2\u003e\r\n\r\n\u003cp\u003eAt boot time, the read-only firmware extends TPM PCR0 with the status of the developer and recovery mode switches. The value of PCR0 can later be quoted using a key that has been verified as an Attestation Identity Key (AIK). The quote, in combination with the AIK credential, gives assurance that the reported PCR0 value is accurate. While assurance of the PCR0 value is very strong, assurance that this correctly reflects the device mode is weaker because of the reliance on read-only firmware to extend PCR0. It is nonetheless useful for reporting policy compliance. This PCR0 quote is not available outside of Chrome OS unless the user or device-owner has consented to remote attestation of the device.\u003c/p\u003e\r\n\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Chrome-OS-Specific-TPM-Configuration\" /\u003eChrome OS-Specific TPM Configuration\u003c/h2\u003e\r\n\r\n\u003cp\u003eUnder Chrome OS, there are a few configuration settings for the TPM that may differ from other operating systems:\u003c/p\u003e\r\n\r\n\u003cul\u003e\r\n\u003cli\u003eTPM ownership, as discussed above, is automatic and random. While the user may choose to write the random owner password down, it is never used. Rather, TPM ownership is established merely to enable the cryptographic features (such as using keys wrapped directly or indirectly by the SRK) that Chrome OS uses in the TPM.\u003c/li\u003e\r\n\u003cli\u003eThe Storage Root Key (SRK) is unrestricted so that it can be used without the owner password. Since the TPM is used as a generic cryptographic device, and Chrome OS manages clearing the TPM in firmware as necessary, unrestricted use of the SRK is allowable.\u003c/li\u003e\r\n\u003cli\u003eIn Chrome OS, the TPM is only used locally on the Chrome device. Chrome OS uses TrouSerS for communication with the TPM, which has been patched to use a UNIX domain socket instead of a TCP socket.\u003c/li\u003e\r\n\u003cli\u003eUnder Chrome OS, physical presence is disabled on every boot by the read-write firmware.\u003c/li\u003e\r\n\u003c/ul\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/tpm-usage"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7950208076219910713"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7950208076219910713"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7950208076219910713"}],"author":[{"email":{"$t":"josiew@google.com"}}],"sites$pageName":{"$t":"tpm-usage"},"sites$revision":{"$t":"11"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1595545453430956695"},"published":{"$t":"2013-12-20T17:04:35.186Z"},"updated":{"$t":"2013-12-20T17:04:35.216Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-20T17:04:35.186Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-12-20 at 9.03.31 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1595545453430956695"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/432234779998665157"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/testing/adding-performance-tests/Screen%20Shot%202013-12-20%20at%209.03.31%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1595545453430956695"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1595545453430956695"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1595545453430956695"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1595545453430956695"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"WCl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4351538001344192696"},"published":{"$t":"2013-06-05T09:22:51.830Z"},"updated":{"$t":"2013-12-19T16:06:28.176Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-19T16:06:26.151Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Making Autofill Into a Layered Component"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-off\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Objective\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eObjective\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Analysis\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eAnalysis\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Plan\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ePlan\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Status\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eStatus\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Help-How-Do-I-Get-My-Autofill-Related-Work-Done-\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eHelp! How Do I Get My Autofill-Related Work Done?\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Objective\" /\u003e\u003cfont size\u003d\"4\"\u003eObjective\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003eRestructure \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003ecomponents/autofill\u003c/code\u003e\u003c/font\u003e into a \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design\"\u003elayered component\u003c/a\u003e in order to enable iOS to cleanly share code in \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003ecomponents/autofill/browser\u003c/code\u003e\u003c/font\u003e and \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003ecomponents/autofill/common\u003c/code\u003e\u003c/font\u003e. Concretely, eliminate usage of the content layer from \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003ecomponents/autofill\u003c/code\u003e\u003c/font\u003e code that iOS wishes to share (for details on why iOS will not be using the content layer, see the motivation and background sections of the layered components \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design\"\u003edesign document\u003c/a\u003e).\u003c/font\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Analysis\" /\u003e\u003cfont size\u003d\"4\"\u003eAnalysis\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003eOn the browser side, Autofill's usage of the content layer falls into several broad categories:\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eReceiving communication from the renderer/external world.\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eObserving WebContents\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eReceiving IPC\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eListening for notifications\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eCommunicating to the renderer via IPC.\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eQuerying the external world for information.\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003ee.g., asking BrowserContext whether it is off-the-record\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003ee.g., getting the values of UserPrefs\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eConvenience usages\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eThe FormData struct has a content::SSLStatus field\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eAutofillManager uses a constant defined in the content layer to reference HTTPS scheme\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Plan\" /\u003e\u003cfont size\u003d\"4\"\u003ePlan\u003c/font\u003e\u003c/h2\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eIntroduce AutofillDriver interface to abstract communication from autofill core code to the renderer\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eFeatures:\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eInterface declared in shared browser code\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eContent-based implementation will use IPC to communicate to the renderer\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eiOS-based implementation will forward calls directly to iOS autofill UI implementation\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eContent-based: AutofillDriverImpl class that will live in autofill's content driver and handle communication from the renderer/external world\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eWill implement the AutofillDriver interface\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eWill be a WebContentsObserver, using observations to drive flow of the shared browser code\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eWill be a WebContentsUserData, providing access to per-tab instances of shared browser classes\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eWill receive IPC, transforming the received messages into method calls on shared browser code\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eWill listen for notifications, transforming them into method calls on shared browser code\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eiOS-based: Introduce a conceptually-similar AutofillDriverIOS class that will live in autofill's iOS driver\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eExtend AutofillDriver interface to supply the information that shared code needs from the external world\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eNew interfaces will replace direct calls that the shared code makes on the content API (e.g., to BrowserContext)\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eContent-based implementation will back these interfaces by content layer objects\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eiOS implementation will back these interfaces by iOS web layer objects\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cb\u003e\u003cfont size\u003d\"3\"\u003eEliminate convenience usages on a case-by-case basis\u003c/font\u003e\u003c/b\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003ee.g., for SSLStatus, determine exactly what SSL information FormData needs and have FormData maintain just that information\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Status\" /\u003e\u003cfont size\u003d\"4\"\u003eStatus\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003ePut autofill/components into the structure of a layered component with temporary DEPS allowances for violations (and a comment instructing devs not to add any more allowances) \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eCompleted over a progression of several CLs\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eCL finishing the move and introducing DEPS restrictions with temporary allowances: \u003ca href\u003d\"https://chromiumcodereview.appspot.com/17392006\"\u003ehttps://chromiumcodereview.appspot.com/17392006\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/16286020/\"\u003eIntroduce the AutofillDriver interface\u003c/a\u003e \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eIntroduce the content-based AutofillDriverImpl class and incrementally expand it to:\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/16286020/\"\u003eAbstract WebContentsObserver from shared code\u003c/a\u003e \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/17225008/\"\u003eAbstract WebContentsUserData from shared code\u003c/a\u003e \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/17893010/\"\u003eAbstract listening for notifications from shared code\u003c/a\u003e \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/17382007/\"\u003eAbstract IPC reception from shared code\u003c/a\u003e \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eExtend the AutofillDriver interface to abstract sending IPC from autofill core code \u003cb\u003e[STARTED]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/17572015/\"\u003ehttps://codereview.chromium.org/17572015/\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/18563002/\"\u003ehttps://codereview.chromium.org/18563002/\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eSeveral other CLs, similar in nature\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eIntroduce the AutofillDriverIOS class \u003cb\u003e[NOT STARTED]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eEliminate convenience usages of the content layer \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eAbstract BrowserContext usage \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eSeveral CLs, see tracking \u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d303034\"\u003ebug\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eExample \u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d303047\"\u003eCL\u003c/a\u003e abstracting BrowserContext::IsOffTheRecord()\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eAbstract BrowserThread usage \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eSeveral CLs, see tracking \u003ca href\u003d\"https://code.google.com/p/chromium/issues/detail?id\u003d303009\"\u003ebug\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eExample \u003ca href\u003d\"https://codereview.chromium.org/25783002\"\u003eCL\u003c/a\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003ca href\u003d\"https://codereview.chromium.org/108013004\"\u003eBuild Autofill core code and component-level unittests on iOS\u003c/a\u003e \u003cb\u003e[DONE]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003eChange all Autofill core unittests to be component-level unittests \u003cb\u003e[NOT STARTED]\u003c/b\u003e\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Help-How-Do-I-Get-My-Autofill-Related-Work-Done-\" /\u003e\u003cfont size\u003d\"4\"\u003eHelp! How Do I Get My Autofill-Related Work Done?\u003c/font\u003e\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003eThe intended audience of this section is engineers working on components/autofill, and its purpose is to answer questions of the form \"I need to do Foo, but I can't do it via Bar anymore! What do I do?\".\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eHow do I get an AutofillManager instance/AutofillExternalDelegate instance from a WebContents instance? \u003c/b\u003eGet the AutofillDriver instance (which is a WebContentsUserData) from the WebContents and then call the relevant accessor of AutofillDriver.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eHow do I take some action in shared code based on a new IPC message/WebContents observation/notification? \u003c/b\u003eAdd a new method(s) as appropriate in shared code to implement the desired behavior; then have AutofillDriver listen for the IPC/observation/notification and invoke the new flow in shared code as appropriate.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eWhere are the common/ and browser/ directories under autofill/? \u003c/b\u003eCode that is shared with iOS has been moved to \u003ccode\u003eautofill/core/\u003c/code\u003e; code that is not shared with iOS has been moved to \u003ccode\u003eautofill/content/\u003c/code\u003e.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eI need to use the content layer in foo.cc, but I'm getting a DEPS violation when I try to upload! \u003c/b\u003eThe reason for the DEPS violation is that foo.cc is used on iOS and thus cannot use the content layer directly. See if you can implement your desired flow via one of the suggestions earlier in this set of questions. If not, consider whether the information that you need to obtain from the content layer can be done by extending one of the existing delegate interfaces via which shared code obtains information indirectly from the content layer. If all else fails, contact blundell@chromium.org to assist.\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont size\u003d\"3\"\u003e\u003cb\u003eI want to add a new browser-side file; where should I put it? \u003c/b\u003eIt depends on whether you think that the functionality of the file should be shared on iOS. If so, put it in \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003eautofill/core/browser\u003c/code\u003e\u003c/font\u003e, in which case it cannot reference the content layer directly. Otherwise, put it under \u003cfont face\u003d\"courier new, monospace\"\u003e\u003ccode\u003eautofill/content/browser/\u003c/code\u003e\u003c/font\u003e, in which case it can freely reference the content layer. In cases of doubt, feel free to contact blundell@chromium.org or stuartmorgan@chromium.org.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4328920814080995024"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-technical-approach/making-autofill-into-a-layered-component"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4351538001344192696"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4351538001344192696"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4351538001344192696"}],"author":[{"name":{"$t":"Colin Blundell"},"email":{"$t":"blundell@chromium.org"}}],"sites$pageName":{"$t":"making-autofill-into-a-layered-component"},"sites$revision":{"$t":"21"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1514852192086277509"},"published":{"$t":"2013-12-13T05:47:53.300Z"},"updated":{"$t":"2013-12-13T22:37:01.541Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-13T22:37:00.118Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Implicit System Dependencies"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Rationale\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eRationale\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Guidelines\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eGuidelines\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Libraries\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eLibraries\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Programs\"\u003e\u003cstrong\u003e3.2 \u003c/strong\u003ePrograms\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Compilation\"\u003e\u003cstrong\u003e3.3 \u003c/strong\u003eCompilation\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Exceptions\"\u003e\u003cstrong\u003e3.4 \u003c/strong\u003eExceptions\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Implementation\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eImplementation\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\r\n\u003cp\u003eGentoo has the concept of an \u003ca href\u003d\"http://devmanual.gentoo.org/general-concepts/dependencies/\" rel\u003d\"nofollow\"\u003eimplicit system dependency\u003c/a\u003e. The idea is simply put: there are a number of packages that every system will need to function at any level (to boot, build, etc...), and rather than have every other package in the tree depend on them, we stick it in the @system set instead. Then things in that set can be ignored when declaring a package's dependency (build and run time).\u003c/p\u003e\r\n\u003cp\u003eIt's a convenient way of:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eavoiding lots of circular dependencies\u003c/li\u003e\r\n\u003cli\u003eduplicating the same basic set of dependencies over and over in packages\u003c/li\u003e\r\n\u003cli\u003eswapping out one set of packages for another (like using \"busybox\" instead of \"coreutils\" in an embedded system)\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eConsider this: how useful is a system if you don't have programs like sh, cat, grep, ls, mv, sed, test? Or a C library? Or to try to compile code, but have no compiler/assembler/linker? Is it really useful for developers to analyze every single shell script/line of source that goes into a distribution to see which tools are run (including every time a package releases a new version)? Or do we simply state up front: at run time, you may assume that a certain baseline of libraries/programs exist, and at build time, certain libraries/compilers exist?\u003c/p\u003e\r\n\u003cp\u003eThe question is obviously rhetorical -- developer time is better spent doing real work than keeping track of these things.\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Rationale\" /\u003eRationale\u003c/h2\u003e\r\n\u003cp\u003eGentoo doesn't explicitly define what packages qualify as part of the implicit system dependency. It alludes to them by talking about the @system set, but then tempers that requirement by stating not all things in it may be ignored. Chromium OS refines the concept by splitting them: there are \"the implicit system dependencies\" and there is the \"@system set\". The former concept is what we want to define, and the latter is merely a (partial) consequence of the first.\u003c/p\u003e\r\n\u003cp\u003eMore specifically, we don't want to say \"the sys-apps/coreutils package is part of the implicit system dependencies\". Instead, we say \"`mv` and `ls` are part of the implicit system dependencies\". Then, with that declaration in hand, it is obvious to say the default @system set includes the sys-apps/coreutils package.\u003c/p\u003e\r\n\u003cp\u003eThe reason for this is that the coreutils package includes a ton of utilities, many of which we would not consider part of the implicit system set. While it's unreasonable to say \"if you use `mv` or `touch` or `ls` or `echo` or `cat`, you have to depend on coreutils\" due to their high prevalence, you can make a reasonable case that if your program runs `pinky`, then you probably should depend on sys-apps/coreutils. The number of packages that use that tool is low (if there are any at all).\u003c/p\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Guidelines\" /\u003eGuidelines\u003c/h2\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Libraries\" /\u003eLibraries\u003c/h3\u003e\r\n\u003cp\u003eThe only library packages you may assume exist in the implicit system set are the C library and runtime libraries provided by the compiler. This isn't just the main C library, but encompasses all the libraries that \u003ca href\u003d\"http://pubs.opengroup.org/onlinepubs/9699919799/\" rel\u003d\"nofollow\"\u003ePOSIX\u003c/a\u003e documents like:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003e-lc\u003c/li\u003e\r\n\u003cli\u003e-lcrypt\u003c/li\u003e\r\n\u003cli\u003e-ldl\u003c/li\u003e\r\n\u003cli\u003e-lm\u003c/li\u003e\r\n\u003cli\u003e-lpthread\u003c/li\u003e\r\n\u003cli\u003e-lresolv\u003c/li\u003e\r\n\u003cli\u003e-lrt\u003c/li\u003e\r\n\u003cli\u003e-lutil\u003c/li\u003e\u003c/ul\u003e\r\n\u003cp\u003eFor internal runtime libraries that the compiler provides (like -lstdc++ and -lgcc and -lgcc_s and -lasan and the rest), you should not depend on these yourself.\u003c/p\u003e\u003cp\u003eFor all other third party libraries like -lz or -luuid or -lblkid or -lcrack, you must depend on the relevant package that provides that library.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Programs\" /\u003ePrograms\u003c/h3\u003e\r\n\u003cp\u003eTypically, if the program you wish to use is defined by \u003ca href\u003d\"http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html\" rel\u003d\"nofollow\"\u003ePOSIX\u003c/a\u003e or the \u003ca href\u003d\"http://www.pathname.com/fhs/\" rel\u003d\"nofollow\"\u003eFHS\u003c/a\u003e, you do not have to depend on it. For the exact list though, please consult the implementation below.\u003c/p\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Compilation\" /\u003eCompilation\u003c/h3\u003e\r\n\u003cp\u003eIn order to build from source, you do not have to have build time dependencies on:\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003ecompiler (e.g. sys-devel/gcc and the utils/frontends it provides)\u003c/li\u003e\r\n\u003cli\u003eassembler/linker/archiver/strip/etc... (e.g. sys-devel/binutils)\u003c/li\u003e\r\n\u003cli\u003eOS headers (e.g. sys-kernel/linux-headers)\u003c/li\u003e\r\n\u003cli\u003emake (e.g. sys-devel/make)\u003c/li\u003e\r\n\u003cli\u003etar (e.g. app-arch/tar)\u003c/li\u003e\r\n\u003cli\u003egzip/bzip2 (e.g. app-arch/gzip \u0026amp; app-arch/bzip2)\u003c/li\u003e\r\n\u003cli\u003eany other runtime package listed in the Programs list above\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Exceptions\" /\u003eExceptions\u003c/h3\u003e\r\n\u003cp\u003eBecause it wouldn't be a good set of guidelines without exceptions, here they are.\u003c/p\u003e\r\n\u003cul\u003e\u003cli\u003eIf your package is binary only (no source is available to the ebuild), then you should depend on the exact libraries that it is linked against (e.g. that will frequently be sys-libs/glibc and sys-libs/gcc-libs)\u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Implementation\" /\u003eImplementation\u003c/h2\u003e\r\n\u003cp\u003eYou can find the default implicit system package in the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/virtual/implicit-system\"\u003echromiumos-overlay\u003c/a\u003e. It documents the various packages it pulls in and gives reasoning as to why each one exists.\u003c/p\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7575192847733958161"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/implicit-system"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1514852192086277509"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1514852192086277509"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1514852192086277509"}],"author":[{"name":{"$t":"Mike Frysinger"},"email":{"$t":"vapier@chromium.org"}}],"sites$pageName":{"$t":"implicit-system"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDspeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3402618879171940496"},"published":{"$t":"2013-12-11T20:24:51.011Z"},"updated":{"$t":"2013-12-11T23:44:27.663Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-11T23:44:26.158Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Simple loop example"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eHere we show the steps that Subzero takes in translating a simple loop example.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor translating this example to native code, we assume a fairly constrained platform: x86-32 with only 3 registers (eax, ecx, edx) available for local register allocation, and no global register allocation.\u003cbr /\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eStart with the following C example, which computes the reduction of an integer array.\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003eint simple_loop(int *a, int n) {\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e  int sum \u003d 0;\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e  for (int i \u003d 0; i \u0026lt; n; ++i) {\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e    sum +\u003d a[i];\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e  }\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e  return sum;\u003c/code\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eThe corresponding PNaCl bitcode after compiling with \u003ccode\u003epnacl-clang -O2\u003c/code\u003e is the following:\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003edefine internal i32 @simple_loop(i32 %a, i32 %n) {\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003eentry:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %cmp4 \u003d icmp sgt i32 %n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br i1 %cmp4, label %for.body, label %for.end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003efor.body:                                         ; preds \u003d %for.body, %entry\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %i.06 \u003d phi i32 [ %inc, %for.body ], [ 0, %entry ]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %sum.05 \u003d phi i32 [ %add, %for.body ], [ 0, %entry ]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %gep_array \u003d mul i32 %i.06, 4\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %gep \u003d add i32 %a, %gep_array\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %gep.asptr \u003d inttoptr i32 %gep to i32*\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %0 \u003d load i32* %gep.asptr, align 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %add \u003d add i32 %0, %sum.05\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %inc \u003d add i32 %i.06, 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %cmp \u003d icmp slt i32 %inc, %n\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br i1 %cmp, label %for.body, label %for.end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003efor.end:                                          ; preds \u003d %for.body, %entry\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  %sum.0.lcssa \u003d phi i32 [ 0, %entry ], [ %add, %for.body ]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret i32 %sum.0.lcssa\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eGenerate high-level Vanilla ICE, including lowering phi instructions.  Where possible, v_*_phi assignments are pushed up to just past their last use in the basic block, and past a compare/branch that ends the basic block.\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_c \u003d icmp sgt v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br v_c, l_body, l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_i \u003d phi [v_inc, l_body], [0, l_entry]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i \u003d v_i_phi\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_sum \u003d phi [v_add, l_body], [0, l_entry]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum \u003d v_sum_phi\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_t1 \u003d mul v_i, 4\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_t2 \u003d add v_a, v_t1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_elt \u003d load v_t2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_add \u003d add v_elt, v_sum\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum_phi \u003d v_add\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e  v_sum2_phi \u003d v_add\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_inc \u003d add v_i, 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e  v_i_phi \u003d v_inc\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e  v_c2 \u003d icmp slt v_inc, v_n\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br v_c2, l_body, l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_sum2 \u003d phi [0, l_entry], [v_add, l_body]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2 \u003d v_sum2_phi\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret v_sum2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eLiveness analysis determines which source operands in each instruction are the end of the operand's live range.  As a bonus, it also determines the set of live operands at the beginning of each basic block.  If liveness analysis is omitted, we assume all operands are live at the beginning of every basic block, and no operands' live ranges end in any instruction.  The results are the \u003ccode\u003eLIVE\u003c/code\u003e annotations at the start of each basic block, and the \u003ccode\u003eLIVEEND\u003c/code\u003e annotations on each instruction.\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry: // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVE\u003d{v_a,v_n}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2_phi \u003d 0;\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_c \u003d icmp sgt v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br v_c, l_body, l_end // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_c}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body: // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVE\u003d{v_i_phi,v_sum_phi,v_a,v_n}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i \u003d v_i_phi              // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_i_phi}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum \u003d v_sum_phi          // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_sum_phi}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_t1 \u003d mul v_i, 4\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_t2 \u003d add v_a, v_t1       // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_t1}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_elt \u003d load v_t2          // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_t2}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_add \u003d add v_elt, v_sum   // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_elt,v_sum}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum_phi \u003d v_add\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2_phi \u003d v_add         // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_add}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_inc \u003d add v_i, 1         // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_i}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i_phi \u003d v_inc\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e  v_c2 \u003d icmp slt v_inc, v_n // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_inc}\u003c/span\u003e\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br v_c2, l_body, l_end     // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_c2}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end: // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVE\u003d{v_sum2_phi}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2 \u003d v_sum2_phi // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_sum2_phi}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret v_sum2          // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eLIVEEND\u003d{v_sum2}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eAddressing mode inference (x86 only) identifies operands that pattern-match to an expression suitable to the special x86 addressing modes.  The results are an annotation on the use of the calculated address, as well as annotations on the uses of the core operands as the subexpressions are built up into the calculated address.  These annotations are labeled \u003ccode\u003eADDROPT\u003c/code\u003e and \u003ccode\u003eADDR\u003c/code\u003e, respectively.  The code selector makes use of the \u003ccode\u003eADDROPT\u003c/code\u003e annotation, and the local register manager takes the \u003ccode\u003eADDR\u003c/code\u003e annotations into account when assigning registers.\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry: // LIVE\u003d{v_a,v_n}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_c \u003d icmp sgt v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br v_c, l_body, l_end // LIVEEND\u003d{v_c}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body: // LIVE\u003d{v_i_phi, v_sum_phi, v_a, v_n}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i \u003d v_i_phi              // LIVEEND\u003d{v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum \u003d v_sum_phi          // LIVEEND\u003d{v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_t1 \u003d mul v_i, 4          // \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eADDR\u003d{v_i}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_t2 \u003d add v_a, v_t1       // LIVEEND\u003d{v_t1}, \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eADDR\u003d{v_a}\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_elt \u003d load v_t2          // LIVEEND\u003d{v_t2}, \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eADDROPT\u003dv_a+4*v_i+0\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_add \u003d add v_elt, v_sum   // LIVEEND\u003d{v_elt, v_sum}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum_phi \u003d v_add\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2_phi \u003d v_add         // LIVEEND\u003d{v_add}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_inc \u003d add v_i, 1         // LIVEEND\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_i_phi \u003d v_inc\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e  v_c2 \u003d icmp slt v_inc, v_n // LIVEEND\u003d{v_inc}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br v_c2, l_body, l_end     // LIVEEND\u003d{v_c2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end: // LIVE\u003d{v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  v_sum2 \u003d v_sum2_phi // LIVEEND\u003d{v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret v_sum2          // LIVEEND\u003d{v_sum2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eInstruction selection includes local register allocation, using 3 registers but calling them \u003ccode\u003er1\u003c/code\u003e, \u003ccode\u003er2\u003c/code\u003e, and \u003ccode\u003er3\u003c/code\u003e so that the specific mappings to \u003ccode\u003eeax\u003c/code\u003e, \u003ccode\u003eecx\u003c/code\u003e, and \u003ccode\u003eedx\u003c/code\u003e can be deferred.  In the code below, for each instruction, we retain the originating Vanilla ICE instruction in a comment for clarity, and each low-level ICE instruction is annotated with the local register manager state.  This state includes the LRU order (the first register listed is the next register to be given out), and the set of operands and constants available in each register.  When the instruction selection code works with the local register manager, the selector may take advantage of operator commutativity to minimize the instruction expansion (see the \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003ehighlighted\u003c/span\u003e instruction).\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry: // LIVE\u003d{v_a,v_n}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  // v_i_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r1, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i_phi, r1 // r2\u003d{}, r3\u003d{}, r1\u003d{0,v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  // v_sum_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r2, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum_phi, r2 // r3\u003d{}, r1\u003d{0,v_i_phi}, r2\u003d{0,v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  // v_sum2_phi \u003d 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r3, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2_phi, r3 // r1\u003d{0,v_i_phi}, r2\u003d{0,v_sum_phi}, r3\u003d{0,v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  cmp v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ble l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br l_body\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body: // LIVE\u003d{v_i_phi, v_sum_phi, v_a, v_n}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_i \u003d v_i_phi // LIVEEND\u003d{v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r1, v_i_phi // r2\u003d{}, r3\u003d{}, r1\u003d{v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i, r1 // r2\u003d{}, r3\u003d{}, r1\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_sum \u003d v_sum_phi // LIVEEND\u003d{v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r2, v_sum_phi // r3\u003d{}, r1\u003d{v_i}, r2\u003d{v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum, r2 // r3\u003d{}, r1\u003d{v_i}, r2\u003d{v_sum}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_t1 \u003d mul v_i, 4 // ADDR\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r3, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  shl r3, 2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_t1, r3 // r2\u003d{v_sum}, r3\u003d{v_t1}, r1\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_t2 \u003d add v_a, v_t1 // LIVEEND\u003d{v_t1}, ADDR\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r2, v_a // r3\u003d{v_t1}, r1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  \u003cspan style\u003d\"background-color:rgb(255,255,0)\"\u003eadd r3, r2\u003c/span\u003e\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_t2, r3 // r3\u003d{v_t2}, r1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_elt \u003d load v_t2 // LIVEEND\u003d{v_t2}, ADDROPT\u003dv_a+4*v_i+0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r3, [r2+4*r1]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_elt, r3 // r1\u003d{v_i}, r2\u003d{v_a}, r3\u003d{v_elt}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_add \u003d add v_elt, v_sum // LIVEEND\u003d{v_elt, v_sum}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add r3, v_sum\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_add, r3 // r1\u003d{v_i}, r2\u003d{v_a}, r3\u003d{v_add}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_sum_phi \u003d v_add // PHI\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum_phi, r3 // \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003er1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/span\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e, r3\u003d{v_add,v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_sum2_phi \u003d v_add // PHI, LIVEEND\u003d{v_add}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2_phi, r3 // \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003er1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/span\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e, r3\u003d{v_add,v_sum_phi,v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e \u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e \u003c/code\u003e\u003c/span\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e//v_inc \u003d add v_i, 1 // LIVEEND\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add r1, 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_inc, r1 // r2\u003d{v_a}, r3\u003d{v_add\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e,v_sum_phi,v_sum2_phi\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e}, r1\u003d{v_inc}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_i_phi \u003d v_inc // PHI\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mv v_i_phi, r1 // r2\u003d{v_a}, r3\u003d{v_add\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e,v_sum_phi,v_sum2_phi\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e}, r1\u003d{v_inc,v_i_phi}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e//v_c2 \u003d icmp slt v_inc, v_n // LIVEEND\u003d{v_inc}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  cmp r1, v_n\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //br v_c2, l_body, l_end // LIVEEND\u003d{v_c2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  blt l_body\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end: // LIVE\u003d{v_sum2_phi}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //v_sum2 \u003d v_sum2_phi // LIVEEND\u003d{v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r1, v_sum2_phi\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2, r1 // r1\u003d{v_sum2_phi,v_sum2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  //ret v_sum2 // LIVEEND\u003d{v_sum2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eMultiblock register allocation starts by identifying register/operand candidates (\u003ccode\u003eCAND\u003c/code\u003e) for each basic block in which the operand is live on entry and is the first value assigned to the register in the basic block.  These candidates are used in conjunction with physical register preferences to decide on mappings between \u003ccode\u003er1/r2/r3\u003c/code\u003e and \u003ccode\u003eeax/ecx/edx\u003c/code\u003e in each basic block.  For example, \u003ccode\u003emov eax, r1\u003c/code\u003e creates a preference for \u003ccode\u003er1\u003c/code\u003e to be \u003ccode\u003eeax\u003c/code\u003e in the last basic block, and that preference propagates when possible to the predecessor basic blocks.  Edges may need to be split to add compensation code when the preferences are overconstrained.\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry: // LIVE\u003d{v_a,v_n}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// CAND\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// REG\u003d{r3:eax, r1:ecx,r2:edx}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r1, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i_phi, r1 // r2\u003d{}, r3\u003d{}, r1\u003d{0,v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r2, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum_phi, r2 // r3\u003d{}, r1\u003d{0,v_i_phi}, r2\u003d{0,v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r3, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2_phi, r3 // r1\u003d{0,v_i_phi}, r2\u003d{0,v_sum_phi}, r3\u003d{0,v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  cmp v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ble l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br l_body\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body_split1:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, eax // mov r2:v_sum_phi, r3:v_sum_phi\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body: // LIVE\u003d{v_i_phi, v_sum_phi, v_a, v_n}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// CAND\u003d{v_i_phi:r1,v_sum_phi:r2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// REG\u003d{r3:eax, r1:ecx,r2:edx}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ////mov r1, v_i_phi // r2\u003d{}, r3\u003d{}, r1\u003d{v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i, r1 // r2\u003d{}, r3\u003d{}, r1\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ////mov r2, v_sum_phi // r3\u003d{}, r1\u003d{v_i}, r2\u003d{v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum, r2 // r3\u003d{}, r1\u003d{v_i}, r2\u003d{v_sum}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r3, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  shl r3, 2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_t1, r3 // r2\u003d{v_sum}, r3\u003d{v_t1}, r1\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r2, v_a // r3\u003d{v_t1}, r1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add r3, r2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_t2, r3 // r3\u003d{v_t2}, r1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov r3, [r2+4*r1]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_elt, r3 // r1\u003d{v_i}, r2\u003d{v_a}, r3\u003d{v_elt}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add r3, v_sum\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_add, r3 // r1\u003d{v_i}, r2\u003d{v_a}, r3\u003d{v_add}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum_phi, r3 // \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"line-height:1;font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003er1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/span\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\" style\u003d\"line-height:1;font-size:10pt\"\u003e\u003ccode\u003e, r3\u003d{v_add,v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2_phi, r3 // \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"line-height:1;font-size:10pt;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003er1\u003d{v_i}, r2\u003d{v_a}\u003c/code\u003e\u003c/span\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\" style\u003d\"line-height:1;font-size:10pt\"\u003e\u003ccode\u003e, r3\u003d{v_add,v_sum_phi,v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add r1, 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_inc, r1 // \u003c/code\u003e\u003c/font\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\" style\u003d\"line-height:1;font-size:10pt\"\u003e\u003ccode\u003er2\u003d{v_a}, r3\u003d{v_add\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"line-height:1;font-size:10pt;background-color:transparent;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e,v_sum_phi,v_sum2_phi\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"line-height:1;font-size:10pt;background-color:transparent;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e}, r1\u003d{v_inc}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i_phi, r1 // \u003c/code\u003e\u003c/font\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\" style\u003d\"line-height:1;font-size:10pt\"\u003e\u003ccode\u003er2\u003d{v_a}, r3\u003d{v_add\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"line-height:1;font-size:10pt;background-color:transparent;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e,v_sum_phi,v_sum2_phi\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"line-height:1;font-size:10pt;background-color:transparent;color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003ccode\u003e}, r1\u003d{v_inc,v_i_phi}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e  cmp r1, v_n\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  blt l_body_split1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end: // LIVE\u003d{v_sum2_phi}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// CAND\u003d{v_sum2_phi:r1}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// REG\u003d{r1:eax, r2:ecx,r3:edx}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ////mov r1, v_sum2_phi\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2, r1 // r1\u003d{v_sum2_phi,v_sum2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, r1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eAfter physical register substitution:\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry: // LIVE\u003d{v_a,v_n}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// CAND\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// REG\u003d{r3:eax, r1:ecx,r2:edx}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov ecx, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i_phi, ecx // edx\u003d{}, eax\u003d{}, ecx\u003d{0,v_i_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, ecx\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum_phi, edx // eax\u003d{}, ecx\u003d{0,v_i_phi}, edx\u003d{0,v_sum_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, ecx\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2_phi, eax // ecx\u003d{0,v_i_phi}, edx\u003d{0,v_sum_phi}, eax\u003d{0,v_sum2_phi}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  cmp v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ble l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br l_body\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body_split1:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, eax\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body: // LIVE\u003d{v_i_phi, v_sum_phi, v_a, v_n}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// CAND\u003d{v_i_phi:r1,v_sum_phi:r2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// REG\u003d{r3:eax, r1:ecx,r2:edx}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i, ecx // edx\u003d{}, eax\u003d{}, ecx\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum, edx // eax\u003d{}, ecx\u003d{v_i}, edx\u003d{v_sum}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, ecx\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  shl eax, 2\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_t1, eax // edx\u003d{v_sum}, eax\u003d{v_t1}, ecx\u003d{v_i}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, v_a // eax\u003d{v_t1}, ecx\u003d{v_i}, edx\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add eax, edx\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_t2, eax // eax\u003d{v_t2}, ecx\u003d{v_i}, edx\u003d{v_a}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, [edx+4*ecx]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_elt, eax // ecx\u003d{v_i}, edx\u003d{v_a}, eax\u003d{v_elt}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add eax, v_sum\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_add, eax // ecx\u003d{v_i}, edx\u003d{v_a}, eax\u003d{v_add}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum_phi, eax // \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;line-height:1;font-size:10pt\"\u003e\u003ccode\u003eecx\u003d{v_i}, edx\u003d{v_a}, eax\u003d{v_add,v_sum_phi}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2_phi, eax // \u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;line-height:1;font-size:10pt\"\u003e\u003ccode\u003eecx\u003d{v_i}, edx\u003d{v_a}, eax\u003d{v_add,v_sum_phi,v_sum2_phi}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add ecx, 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_inc, ecx // edx\u003d{v_a}, eax\u003d{v_add\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e,v_sum_phi,v_sum2_phi\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e}, ecx\u003d{v_inc}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_i_phi, ecx // edx\u003d{v_a}, eax\u003d{v_add\u003c/code\u003e\u003c/font\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e,v_sum_phi,v_sum2_phi\u003c/code\u003e\u003c/span\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:arial,sans-serif;line-height:1;font-size:10pt\"\u003e\u003ccode\u003e}, ecx\u003d{v_inc,v_i_phi}\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e  cmp ecx, v_n\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  blt l_body_split1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end: // LIVE\u003d{v_sum2_phi}, r1\u003d{}, r2\u003d{}, r3\u003d{}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// CAND\u003d{v_sum2_phi:r1}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e// REG\u003d{r1:eax, r2:ecx,r3:edx}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov v_sum2, eax // eax\u003d{v_sum2_phi,v_sum2}\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, eax\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ret\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eDead instruction elimination cleans up dead stores and no-longer-necessary calculations of intermediate components of addressing modes.\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003esimple_loop(v_a, v_n):\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_entry:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;color:rgb(34,34,34);font-family:arial,sans-serif;font-size:10pt\"\u003e\u003ccode\u003e  mov ecx, 0\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, ecx\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, ecx\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  cmp v_n, 0\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  ble l_end\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  br l_body\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body_split1:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, eax\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_body:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e  mov v_sum, edx\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov edx, v_a\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  mov eax, [edx+4*ecx]\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add eax, v_sum\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  add ecx, 1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  cmp ecx, v_n\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003e  blt l_body_split1\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003ccode\u003el_end:\u003c/code\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif;background-color:transparent;font-size:10pt\"\u003e\u003ccode\u003e  ret\u003c/code\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003eIn this example, there are no clear peephole optimizations available, and since only one stack operand is left, there is no need for local variable coalescing.  Thus the difference between the code above and the actual code emitted would involve:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003eFrame setup in the prolog\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003eFrame destruction in the epilog\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003eSubstituting stack frame addressing modes where generic stack operands appear\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003eLoop alignment as desired\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003eSFI sequences\u003c/font\u003e\u003c/li\u003e\u003cli\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003eBundling\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5120367395185403086"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/subzero/simple-loop-example"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3402618879171940496"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3402618879171940496"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3402618879171940496"}],"author":[{"name":{"$t":"Jim Stichnoth"},"email":{"$t":"stichnot@chromium.org"}}],"sites$pageName":{"$t":"simple-loop-example"},"sites$revision":{"$t":"7"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5120367395185403086"},"published":{"$t":"2013-12-11T19:24:16.590Z"},"updated":{"$t":"2013-12-11T20:27:46.017Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-11T20:27:44.496Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Subzero"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cimg src\u003d\"http://www.google.com/chart?chc\u003dsites\u0026amp;cht\u003dd\u0026amp;chdp\u003dsites\u0026amp;chl\u003d%5B%5BPage+listing'%3D20'f%5Cv'a%5C%3D0'10'%3D249'0'dim'%5Cbox1'b%5CF6F6F6'fC%5CF6F6F6'eC%5C0'sk'%5C%5B%22Subpage+Listing%22'%5D'a%5CV%5C%3D12'f%5C%5DV%5Cta%5C%3D10'%3D0'%3D250'%3D297'dim'%5C%3D10'%3D10'%3D250'%3D297'vdim'%5Cbox1'b%5Cva%5CF6F6F6'fC%5CC8C8C8'eC%5C'a%5C%5Do%5CLauto'f%5C\u0026amp;sig\u003d4Bm9qaJUdSqYajg2_Fmi3qRL9R0\" data-type\u003d\"subpages\" data-props\u003d\"align:left;borderTitle:Subpage Listing;displayAs:TOC;maxDepth:6;rootPage:THIS_PAGE;width:250;\" width\u003d\"250\" height\u003d\"300\" style\u003d\"display:block;text-align:left;margin-right:auto;\" /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/subzero"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5120367395185403086"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5120367395185403086"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5120367395185403086"}],"author":[{"name":{"$t":"Jim Stichnoth"},"email":{"$t":"stichnot@chromium.org"}}],"sites$pageName":{"$t":"subzero"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},"published":{"$t":"2011-05-12T17:58:02.776Z"},"updated":{"$t":"2013-12-11T20:27:09.153Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-05-18T06:52:40.146Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"PNaCl"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cimg src\u003d\"http://www.google.com/chart?chc\u003dsites\u0026amp;cht\u003dd\u0026amp;chdp\u003dsites\u0026amp;chl\u003d%5B%5BPage+listing'%3D20'f%5Cv'a%5C%3D0'10'%3D249'0'dim'%5Cbox1'b%5CF6F6F6'fC%5CF6F6F6'eC%5C0'sk'%5C%5B%22Subpage+Listing%22'%5D'a%5CV%5C%3D12'f%5C%5DV%5Cta%5C%3D10'%3D0'%3D250'%3D297'dim'%5C%3D10'%3D10'%3D250'%3D297'vdim'%5Cbox1'b%5Cva%5CF6F6F6'fC%5CC8C8C8'eC%5C'a%5C%5Do%5CLauto'f%5C\u0026amp;sig\u003d4Bm9qaJUdSqYajg2_Fmi3qRL9R0\" data-type\u003d\"subpages\" data-props\u003d\"align:left;borderTitle:Subpage Listing;displayAs:TOC;maxDepth:6;rootPage:THIS_PAGE;width:250;\" width\u003d\"250\" height\u003d\"300\" style\u003d\"display:block;text-align:left;margin-right:auto;\" /\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5663733556794389665"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2062405729464790262"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"}],"author":[{}],"sites$pageName":{"$t":"pnacl"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7937780080709569976"},"published":{"$t":"2013-12-08T15:52:36.192Z"},"updated":{"$t":"2013-12-08T15:57:06.922Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-08T15:57:02.436Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Malicious Extensions Protection"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003cdiv dir\u003d\"ltr\"\u003ehttp://blog.chromium.org/2013/11/protecting-windows-users-from-malicious.html\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6743906577140407009"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/malicious-extensions-protection"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7937780080709569976"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7937780080709569976"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7937780080709569976"}],"author":[{"name":{"$t":"Antony Sargent"},"email":{"$t":"asargent@chromium.org"}}],"sites$pageName":{"$t":"malicious-extensions-protection"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8694043718895226135"},"published":{"$t":"2013-12-04T19:14:43.243Z"},"updated":{"$t":"2013-12-04T19:26:27.418Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-04T19:26:26.265Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Experimenting with generated bitcode"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eSample code (note the \u003ccode\u003enoinline\u003c/code\u003e attribute - makes it simpler to locate the code, otherwise it will get inlined all the way into \u003ccode\u003e_start\u003c/code\u003e):\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003eint __attribute__((noinline)) simple_loop(int *a, int n) {\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  int sum \u003d 0;\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  for (int i \u003d 0; i \u0026lt; n; ++i) {\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    sum +\u003d a[i];\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  }\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  return sum;\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eint main(int argc, char** argv) {\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  return simple_loop((int*)argv[0], argc);\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWill be using the canary SDK here, so set \u003ccode\u003eNACL_SDK_ROOT\u003c/code\u003e to point to an install of the NaCl SDK\u003ccode\u003e /pepper_canary\u003c/code\u003e directory.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRun the compiler to produce optimized bitcode:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003e$NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-clang ~/Downloads/loop.c -O2 -o loop.o2.bc\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv\u003eNote: this is LLVM bitcode:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003e$ $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-dis --file-type loop.o2.bc \u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eloop.o2.bc: LLVM bitcode\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe'll keep it in LLVM bitcode format, because the NaCl bitcode writer/reader can't handle some of the types removed by stripping. So fully finalizing (into a stable pexe) a non-stripped file doesn't currently work.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ccode\u003e$ $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-dis loop.o2.bc |grep -A20 \"define internal i32 @simple_loop\"\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003edefine internal i32 @simple_loop(i32 %a, i32 %n) {\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003eentry:\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %cmp4 \u003d icmp sgt i32 %n, 0\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  br i1 %cmp4, label %for.body, label %for.end\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003efor.body:                                         ; preds \u003d %for.body, %entry\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %i.06 \u003d phi i32 [ %inc, %for.body ], [ 0, %entry ]\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %sum.05 \u003d phi i32 [ %add, %for.body ], [ 0, %entry ]\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %gep_array \u003d mul i32 %i.06, 4\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %gep \u003d add i32 %a, %gep_array\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %gep.asptr \u003d inttoptr i32 %gep to i32*\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %0 \u003d load i32* %gep.asptr, align 1\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %add \u003d add i32 %0, %sum.05\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %inc \u003d add i32 %i.06, 1\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %cmp \u003d icmp slt i32 %inc, %n\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  br i1 %cmp, label %for.body, label %for.end\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003efor.end:                                          ; preds \u003d %for.body, %entry\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  %sum.0.lcssa \u003d phi i32 [ 0, %entry ], [ %add, %for.body ]\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  ret i32 %sum.0.lcssa\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e}\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cbr /\u003e\u003cdiv\u003eFinally, translate that into a .nexe in -O0 mode, asking \u003ccode\u003epnacl-translate\u003c/code\u003e to accept LLVM bitcode explicitly (will be refused otherwise):\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003e$ $NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-translate loop.o2.bc -o loop.x64.nexe -arch x86-64 -O0 --allow-llvm-bitcode-input\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eUse \u003ccode\u003eobjdump\u003c/code\u003e to examine the produced nexe.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/experimenting-with-generated-bitcode"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8694043718895226135"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8694043718895226135"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8694043718895226135"}],"author":[{}],"sites$pageName":{"$t":"experimenting-with-generated-bitcode"},"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2570670174402006764"},"published":{"$t":"2013-12-02T23:10:32.508Z"},"updated":{"$t":"2013-12-02T23:10:32.560Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-02T23:10:32.508Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-12-03 at 10.10.16 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2570670174402006764"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4927629288120429199"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/npapi-deprecation/Screen%20Shot%202013-12-03%20at%2010.10.16%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2570670174402006764"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2570670174402006764"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2570670174402006764"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2570670174402006764"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1759356432325883801"},"published":{"$t":"2013-12-02T23:09:54.468Z"},"updated":{"$t":"2013-12-02T23:09:54.504Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-02T23:09:54.468Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-12-03 at 10.09.10 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1759356432325883801"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4927629288120429199"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/npapi-deprecation/Screen%20Shot%202013-12-03%20at%2010.09.10%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1759356432325883801"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1759356432325883801"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1759356432325883801"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1759356432325883801"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"UCl7JmA7\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8235001577366261484"},"published":{"$t":"2010-08-11T17:35:30.923Z"},"updated":{"$t":"2013-12-02T22:34:59.586Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-12-02T22:34:58.304Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Introduction to Portable Native Client"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Public-Documentation\" /\u003ePublic Documentation\u003c/h2\u003e\u003cdiv\u003e\u003cfont size\u003d\"4\"\u003eIf you want to build a PNaCl application for Chrome, start with the \u003ca href\u003d\"https://developers.google.com/native-client/\"\u003eNative Client developer documentation\u003c/a\u003e\u003c/font\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003eIntroduction\u003c/h2\u003e\u003cdiv\u003e\u003cspan\u003e\u003cfont size\u003d\"2\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNative Client (\u003c/span\u003e\u003ca href\u003d\"https://developers.google.com/native-client/overview\" style\u003d\"text-decoration:none\"\u003e\u003cspan style\u003d\"font-family:Arial;color:rgb(17,85,204);background-color:transparent;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap\"\u003eNaCl\u003c/span\u003e\u003c/a\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e) is a secure sandbox for running untrusted native machine code in the Chrome browser. NaCl programs have special restrictions on the generated code, which are implemented by the compiler toolchain and statically verified at runtime by the trusted NaCl loader.  Chrome apps can embed NaCl modules into their pages, which can perform computations and interact with the embedding page and the system (e.g. to communicate with Javascript or render with OpenGL) via an API called Pepper. Portable Native Client (PNaCl) defines a low-level stable portable intermediate representation (based on the IR used by the open-source LLVM compiler project) which is used as the wire format instead of x86 or ARM machine code. PNaCl consists of a developer toolchain, a specification of the stable portable IR format (along with compiler passes to transform ordinary LLVM IR to the stable form), and a browser component (itself implemented as as NaCl module) which translates the IR into x86-32, x86-64, or ARM machine code. \u003c/span\u003e\u003c/font\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003eThe developer toolchain compiles C and C++ applications to a subset of LLVM bitcode.\u003c/div\u003e\u003cdiv\u003eThese bitcode files (known as \"portable executables\", or \"pexe\" files) represent an Native Client application\u003c/div\u003e\u003cdiv\u003ein a high-level format, which can be translated to native code for execution on any processor supported\u003c/div\u003e\u003cdiv\u003eby NaCl.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe PNaCl toolchain is currently available for Windows, Mac, and Linux.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003ePNaCl currently supports code generation on 4 architectures:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eX86-32\u003c/li\u003e\u003cli\u003eX86-64\u003c/li\u003e\u003cli\u003eARM\u003c/li\u003e\u003cli\u003eMIPS32\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-How-does-PNaCl-work-\" /\u003e\u003cspan style\u003d\"font-size:large\"\u003e\u003cb\u003eHow does PNaCl work?\u003c/b\u003e\u003c/span\u003e\u003c/h2\u003e\u003cdiv\u003ePNaCl is a cross-compiling toolchain, where the target architecture is bitcode. PNaCl recognizes three types of bitcode files:\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cblockquote style\u003d\"margin:0 0 0 40px;border:none;padding:0px\"\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e.bc     - LLVM Bitcode object file. (Analogous to an ELF object file)\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e.a      - Archive of LLVM bitcode objects. (Analogous to a static library archive)\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e.pexe   - LLVM or PNaCl Bitcode executable. (Analogous to an executable file)\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/blockquote\u003e\u003cdiv\u003e\u003cdiv\u003ePNaCl provides the standard tools:\u003c/div\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003cspan style\u003d\"color:rgb(0,96,0);font-family:monospace\"\u003e  pnacl-clang\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e  pnacl-clang++\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont color\u003d\"#006000\" face\u003d\"monospace\"\u003e  pnacl-finalize\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  pnacl-ld\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  pnacl-ar\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  pnacl-nm\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  pnacl-ranlib\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  pnacl-strip\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  pnacl-as\u003c/code\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe pnacl-clang and pnacl-clang++ tools produce LLVM bc files.  The \u003cspan style\u003d\"font-size:10pt\"\u003epnacl-ld\u003c/span\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e \u003c/span\u003e\u003cspan style\u003d\"font-size:10pt\"\u003elinker tool produces a statically linked LLVM pexe.  The pnacl-finalize tool converts an LLVM pexe to a frozen PNaCl bitcode pexe.  Chrome only runs the frozen PNaCl bitcode format, not the standard LLVM bitcode pexe.\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhile chrome can load and translate a frozen pexe directly, there is an additional tool \u003ccode\u003epnacl-translate \u003c/code\u003e\u003cspan style\u003d\"font-size:10pt\"\u003efor generating native code from either LLVM or PNaCl bitcode.  That is useful for debugging (see the Debugging section below).\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px;font-weight:bold\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px;font-weight:bold\"\u003eInstalling the PNaCl Toolchain and Building Examples\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-PNaCl-is-now-available-in-the-naclsdk-updater-https:-developers.google.com-native-client-sdk-download-.-It-is-available-in-pepper_30-and-higher.\" /\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal\"\u003ePNaCl is now available in the naclsdk updater (\u003c/span\u003e\u003ca href\u003d\"https://developers.google.com/native-client/sdk/download\" style\u003d\"font-size:10pt;font-weight:normal\"\u003ehttps://developers.google.com/native-client/sdk/download\u003c/a\u003e\u003cspan style\u003d\"font-size:10pt;font-weight:normal\"\u003e).  It is available in pepper_30 and higher.\u003c/span\u003e\u003c/h3\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eDownload the naclsdk updater, and run \"naclsdk.bat update pepper_XX\" (e.g., pepper_canary).\u003c/li\u003e\u003cli\u003eOnce downloaded, you can set your NACL_SDK_ROOT directory to pepper_XX.\u003c/li\u003e\u003cli\u003e\u003cdiv\u003eSee pepper_canary/examples/ for various examples.  The makefiles in each example directory should be configured to build pnacl pexes and generate manifest files for those pexes.  \u003cspan style\u003d\"font-size:10pt\"\u003eJust set the \"TOOLCHAIN\" environment variable to be \"pnacl\".  E.g.,\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e \"(cd pepper_canary/examples/hello_world; TOOLCHAIN\u003dpnacl CONFIG\u003dRelease make)\".\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/li\u003e\u003cli\u003e\u003cdiv\u003eWith the PNaCl sdk, you can also try compiling some of the \u003ca href\u003d\"http://code.google.com/p/naclports/\"\u003enaclports\u003c/a\u003e examples.  Once you have set the NACL_SDK_ROOT environment variable to point at the pepper directory with pnacl installed, you can run \"make\" to build a naclports target by setting the environment variable  NACL_ARCH to \"pnacl\". E.g., to build dosbox, run\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\"NACL_ARCH\u003dpnacl make dosbox\".\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThat will build the required libraries (e.g., SDL), and build dosbox as a pexe.  Libraries will be installed directly into your SDK and the resulting application (pexe) will be published under out/publish/dosbox.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:20px;font-weight:bold\"\u003eHow to Run Examples in Chrome 31+\u003c/span\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt;background-color:transparent\"\u003eCheck chrome://nacl to see if the PNaCl Translator is already installed.  The ~3-4MB download and install happens in the background.\u003c/span\u003e\u003c/li\u003e\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eIf not already installed, it will be installed on-demand the first time you start a PNaCl application.  A good example application is the \"load progress\" example \u003ca href\u003d\"https://chrome.google.com/webstore/detail/pnacl-examples/mblemkccghnfkjignlmgngmopopifacf\"\u003eincluded here\u003c/a\u003e.\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eAn alternative is to go to chrome://components and click \"Check for update\".\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eFor Chrome 31, the on-demand install can sometimes still fail.  Restart the browser and try again if that happens.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003cli\u003eOnce installed, visit a webpage with a \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/system/errors/NodeNotFound?suri\u003dwuid:gx:14ed7d44e735f46d\" class\u003d\"disabled\"\u003ePNaCl NMF\u003c/a\u003e file that points at your pexe application (the SDK has a create_nmf.py tool that will help you create one).  For example, try loading the samples here: \u003ca href\u003d\"http://gonativeclient.appspot.com/demo\"\u003ehttp://gonativeclient.appspot.com/demo\u003c/a\u003e.\u003c/li\u003e\u003cli\u003eNOTE: In contrast to a NaCl application, the mime type must be application/x-pnacl (not application/x-nacl).\u003c/li\u003e\u003c/ol\u003e\u003cdiv\u003eIf you are having problems check the Chrome JavaScript console and see if there are any error messages.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eHow to report bugs / feedback for PNaCl\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003col\u003e\u003cli\u003eGo to \u003ca href\u003d\"http://code.google.com/p/nativeclient/issues/list\"\u003ehttp://code.google.com/p/nativeclient/issues/list\u003c/a\u003e and file a New Issue.\u003c/li\u003e\u003cli\u003eDescribe the issue.\u003c/li\u003e\u003cli\u003eTag the issue as Component-PNaCl, and Arch-All (or a specific Arch if turns out that it is arch-specific)\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1\" /\u003e\u003cbr /\u003e\u003c/h2\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-PNaCl-Developers\" /\u003ePNaCl Developers\u003c/h2\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003eThe section on developing PNaCl itself has moved to \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/developing-pnacl\" style\u003d\"font-size:10pt\"\u003ehttps://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/developing-pnacl\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/introduction-to-portable-native-client"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8235001577366261484"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8235001577366261484"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8235001577366261484"}],"author":[{}],"sites$pageName":{"$t":"introduction-to-portable-native-client"},"sites$revision":{"$t":"79"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2411997894366814539"},"published":{"$t":"2013-06-27T19:35:50.507Z"},"updated":{"$t":"2013-11-27T18:10:58.452Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-27T18:10:58.446Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Binding Integrity"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cspan\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBinding Integrity Project\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eMotivation\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eOne of the reasons that browsers are easier to compromise than other kinds of client software is that they provide scripting capabilities to a potential attacker. As such, many of the exploits we’ve seen begin with a JavaScript program obtaining and manipulating a freed block of C++ memory. Although the Chrome sandboxing architecture provides excellent protection in this situation, we’d like to prevent JavaScript from getting freed blocks of memory in the first place, so as to make the full exploitation of Chrome even harder than it already is.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eApproach\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAt the time a C++ object is created, we know the corresponding V8 type with which it will be later wrapped for use by V8. We devise an unguessable (by the attacker) representation for each type and put it into the C++ object when it is constructed. We similarly zero out this information at destruction time.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAt the time of a method callback into the C++ object, V8 happens to know the type that is expected to be associated with it. It can then determine what type representation should have been set into the block of memory at creation time, and check that it is still valid. Free blocks will have zeros (or will have been clobbered by heap freelists), and will fail the check. Mis-typed blocks will have different values, and will fail the check. Blocks crafted by the attacker won’t have valid values because the type information representation is unguessable, and will fail the check. At this point the renderer can shoot itself, rather than proceeding into C++ with corrupted memory.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eBut these method invocation calls are very hot code paths, and we don’t want to introduce the overhead of another test and branch here.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAs it turns out, the V8 wrapper objects contain reference pointers back to the blocks of C++ memory, and these do a good job of keeping the memory alive.  Once wrapped, a block is unlikely to be freed.  Hence, most of the cases involve wrapping a block that is already free, and we get nearly the full benefit by doing the check at wrapper creation time only, where performance is not important.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;font-weight:bold;vertical-align:baseline;white-space:pre-wrap\"\u003eImplementation\u003c/span\u003e\u003c/p\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eIt is important that we do not bloat the size of the objects in order to hold this type representation. \u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eMany (but not all) objects wrapped by V8 inherit somewhere from a class called ScriptWrappable, which is a single pointer wide.  It holds a pointer to the C++ object’s wrapper when it is wrapped, or NULL otherwise. We can re-use the slot that holds the the wrapper pointer (which would otherwise be NULL for an unwrapped object) to hold the type information, because we only need the type information for unwrapped objects. Masking in a 1 in the bottom bit (otherwise unused due to aligned pointers) allows us to distinguish between the two cases.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eHence, for objects that are to be checked in this manner, they must inherit somewhere from the ScriptWrappable class (which need not be a common base class).\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThis implies that all objects that inherit from ScriptWrappable and have their own .idl files will have to call\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cspan style\u003d\"white-space:pre\"\u003e\t\u003c/span\u003eScriptWrappable::init(this);\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eas part of their constructors.  Passing “this” is necessary to select between N overloaded versions of ScriptWrappable::init() based upon the type of the object.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe implementations of the N overloaded versions of ScriptWrappable::init() are automatically generated by the .idl compiler (CodeGeneratorV8.pm at present) from the .idl files.  The .idl files need not specify which objects are scriptwrappable, as the compiler can deduce this from type inheritance via partially specialized template tricks. \u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eThe unguessable nature of the type representation is achieved by relying on ASLR to randomize the address of a per-type instance of an existing V8 data structure called WrapperTypeInfo. The address of the WrapperTypeInfo structure for a given type thus already provides what is required here.\u003c/span\u003e\u003c/p\u003e\u003cbr /\u003e\u003cp dir\u003d\"ltr\" style\u003d\"line-height:1.15;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eNote that ScriptWrappable was originally invented to provide a performance improvement. One additional benefit of this change is that making more objects ScriptWrappable makes chrome faster.\u003c/span\u003e\u003c/p\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-size:15px;font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/div\u003e\u003c/span\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6743906577140407009"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/Home/chromium-security/binding-integrity"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2411997894366814539"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2411997894366814539"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2411997894366814539"}],"author":[{"name":{"$t":"Tom Sepez"},"email":{"$t":"tsepez@chromium.org"}}],"sites$pageName":{"$t":"binding-integrity"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"Wil7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7789018718369490338"},"published":{"$t":"2011-11-07T22:27:33.608Z"},"updated":{"$t":"2013-11-25T18:02:45.399Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-25T18:02:43.887Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Accessibility for Chromium Developers"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eNot everyone uses a computer the same way you do! If you're developing code for Chromium, it's important to pay attention to \u003ci\u003eaccessibility - \u003c/i\u003emaking sure that all users get equal access to the product, even if they have a disability or use some alternative method to access their computer.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eAccessibility includes, but is not limited to:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003eFull keyboard accessibility.\u003c/li\u003e\u003cli\u003eSupport for large fonts and very high zoom levels.\u003c/li\u003e\u003cli\u003eSupport for \u003ci\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/user-experience/assistive-technology-support\"\u003escreen readers\u003c/a\u003e\u003c/i\u003e for blind users.\u003c/li\u003e\u003cli\u003eSupport for \u003ci\u003emagnifiers\u003c/i\u003e for low-vision users.\u003c/li\u003e\u003cli\u003eSupport for \u003ci\u003ehigh-contrast modes\u003c/i\u003e for low-vision users.\u003c/li\u003e\u003cli\u003eSupport for \u003ci\u003evoice-control software\u003c/i\u003e for users who cannot type.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv\u003eMore information on how to ensure changes to various parts of the codebase are accessible:\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/windows-accessibility\"\u003eWindows\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/mac-accessibility\"\u003eMac\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/linux-accessibility\"\u003eLinux\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/views-accessibility\"\u003eViews (Windows \u0026amp; Chrome OS)\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/html-accessibility\"\u003eHTML\u003c/a\u003e - also see the page on \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/webui-accessibility-audit\"\u003eWebUI accessibility audits\u003c/a\u003e.\u003c/li\u003e\u003cli\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/webkit-accessibility\"\u003eWebKit/Blink\u003c/a\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Chrome-OS\" /\u003eChrome OS\u003c/h3\u003e\u003cdiv\u003eTest new features on Chrome OS with various accessibility support enabled - in particular, try it with spoken feedback enabled, which uses the ChromeVox screen reader.\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eSee \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/chromevox-on-desktop-linux\" target\u003d\"_blank\"\u003eChromeVox on Desktop Linux\u003c/a\u003e for instructions on how to test ChromeVox on desktop Linux.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Launch-bugs\" /\u003eLaunch bugs\u003c/h3\u003e\u003cdiv\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eNew features must go through accessibility review. When you create a meta bug (Type\u003dMeta), you'll automatically get Dev-AccessibilityReview-No. Just add a comment to the bug when you believe it's ready for review or if you have any questions about what might be needed.\u003c/span\u003e\u003c/div\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Contact-Us\" /\u003eContact Us\u003c/h3\u003e\u003cdiv\u003eGoogle-internal: use the \u003ca href\u003d\"https://groups.google.com/a/google.com/forum/#!forum/chrome-accessibility\" target\u003d\"_blank\"\u003eChrome-Accessibility Group\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003ePublic: the \u003ca href\u003d\"http://groups.google.com/a/chromium.org/group/chromium-accessibility\" target\u003d\"_blank\"\u003eChromium-Accessibility Group\u003c/a\u003e is a public list for discussion of end-user Chromium accessibility issues.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eBugs: tag it with \u003cb\u003eCr-UI-Accessibility\u003c/b\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eFor gory details of how Chromium handles web content accessibility in a multi-process browser, see \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/accessibility\"\u003eAccessibility Technical Documentation\u003c/a\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/accessibility"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7789018718369490338"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7789018718369490338"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7789018718369490338"}],"author":[{"name":{"$t":"Dominic Mazzoni"},"email":{"$t":"dmazzoni@chromium.org"}}],"sites$pageName":{"$t":"accessibility"},"sites$revision":{"$t":"13"}},{"gd$etag":"\"Wyl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4942939941163791063"},"published":{"$t":"2011-11-08T00:22:43.235Z"},"updated":{"$t":"2013-11-21T23:04:27.540Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-21T23:04:25.907Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"HTML Accessibility"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eSignificant parts of the user interface on Chrome and Chrome OS are built using the web platform: HTML, JavaScript, and CSS. These parts of Chrome include \"WebUI\" (e.g. the New Tab Page, Options pages, Bookmark Manager, and the Chrome OS Out-of-box-experience and Sign-in screens), plus many extensions and apps provided by Google. This also applies to help pages and tutorials, such as the Chrome OS welcome page and the Web Store.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eRemember that all of these pages, sites, and apps will be accessed by users with disabilities, including blind users with screen readers, low-vision users who prefer large fonts, people who can't use a mouse, and more. You should use all of the same guidelines you'd use when writing any webpage to make sure it's maximally accessible to all users - there are thousands of resources online, just do a Google search for \"Accessible HTML\".\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Accessibility-Developer-Tools\" /\u003eAccessibility Developer Tools\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003eYou can use the Accessibility Developer Tools extension on the Chrome Web Store as one way to help test! This extension is developed by the Chromium team and will help catch lots of common errors and hopefully make it much easier to catch accessibility errors early in the design process.\u003c/div\u003e\u003cdiv\u003e\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb\" target\u003d\"_blank\"\u003eAccessibility Developer Tools Web\u003c/a\u003e - for auditing any web page other than an app or built-in page\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eA\u003ca href\u003d\"https://chrome.google.com/webstore/a/google.com/detail/accessibility-developer-t/lfcjaoacndhilkpdhgnfjnienfoibnaa\" target\u003d\"_blank\"\u003eccessibility Developer Tools Apps\u003c/a\u003e - for auditing packaged apps\u003c/span\u003e (link is Google-only)\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"https://chrome.google.com/webstore/a/google.com/detail/accessibility-developer-t/eacmnlimniaidhecpinhhfjjilfdaccm\" target\u003d\"_blank\"\u003eAccessibility Developer Tools WebUI\u003c/a\u003e - for Chromium WebUI like chrome://settings/ (link is Google-only)\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003ca href\u003d\"https://github.com/GoogleChrome/accessibility-developer-tools\" target\u003d\"_blank\" rel\u003d\"nofollow\"\u003eBuild it from source\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Auditing-and-Testing\" /\u003eAuditing and Testing\u003c/h2\u003e\u003cdiv\u003eIf you add WebUI tests, an \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/accessibility/webui-accessibility-audit\"\u003eaccessibility audit\u003c/a\u003e, based on the same code as the Accessibility Developer Tools, above, is automatically run on any pages that get tests.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Guidelines\" /\u003eGuidelines\u003c/h2\u003e\u003cdiv\u003eHere are some specific things to think about in particular for Chrome:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eFocus\u003c/b\u003e: Make sure that your page is usable without the mouse. You should be able to press Tab to cycle through all focusable links and controls on the page. It should be very visually apparent when an element has focus, and this indication should be as consistent as possible within a page. It should be impossible for focus to get \"trapped\" in a single control. When the user activates a button or control that opens a dialog or pop-up, place focus inside the new pop-up. When the user closes this pop-up, restore focus to the previous place.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eHover\u003c/b\u003e: Don't ever use Hover as the exclusive way to activate a feature. Make sure you can achieve the same thing by focusing a control with the keyboard.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eVisibility and CSS Animation\u003c/b\u003e: If you use \u003cb\u003eopacity:0\u003c/b\u003e or \u003cb\u003eheight:0\u003c/b\u003e to make something disappear (especially for a nice animation), that item will still be part of the render tree, and screen readers will still read it! You must add some code to wait until the animation finishes and then set the hidden items to \u003cb\u003ehidden\u003c/b\u003e, \u003cb\u003evisibility:hidden\u003c/b\u003e, or \u003cb\u003edisplay:none\u003c/b\u003e.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eColor\u003c/b\u003e: Don't ever use color as the only distinction between one state and another, unless there are two states with very different perceived brightness levels and an accessible annotation for screen reader users. Make sure that there's a lot of contrast between text and the background color.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eSupport 300% zoom\u003c/b\u003e: Make sure everything is still usable at 300% zoom.\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003ePrefer native elements\u003c/b\u003e: Don't use a clickable \u0026lt;div\u0026gt; if you can style a \u0026lt;a\u0026gt; or \u0026lt;button\u0026gt; to look like what you want. If you create a custom control out of a \u0026lt;div\u0026gt;, you must either read up on ARIA and test with at least one screen reader, or send your changes to an accessibility expert for review.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eLabel Images\u003c/b\u003e: All \u0026lt;img\u0026gt; tags must have an alt attribute with an accessible name. If an image is purely decorative or if the accessible name is already present in an adjacent element in the DOM, you can use alt\u003d\"\". Note that alt\u003d\"\" is not the same as leaving out the attribute entirely; if you leave it out, many screen readers will read the filename of the image instead. If you're using a background image that's not purely decorative, use the \u003cb\u003etitle\u003c/b\u003e attribute to provide an accessible name.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- The alt text describes the meaning of the image. --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u0026lt;\u003cb\u003eimg\u003c/b\u003e \u003cb\u003esrc\u003c/b\u003e\u003d\"green_dot.png\" \u003cb\u003ealt\u003c/b\u003e\u003d\"Online\"\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- Purely decorative, so use an empty alt tag. --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u0026lt;\u003cb\u003eimg\u003c/b\u003e \u003cb\u003esrc\u003c/b\u003e\u003d\"separator.png\" \u003cb\u003ealt\u003c/b\u003e\u003d\"\"\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- Use a title attribute for a div with a background image. --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u0026lt;\u003cb\u003ediv\u003c/b\u003e \u003cb\u003estyle\u003c/b\u003e\u003d\"background-image: \u003cb\u003eurl\u003c/b\u003e('john_doe.png')\" \u003cb\u003etitle\u003c/b\u003e\u003d\"John Doe\"\u0026gt;...\u0026lt;\u003cb\u003e/div\u003c/b\u003e\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eLabel Controls\u003c/b\u003e: Controls should have a text label. If the control is a button whose title is text already, nothing else is needed. Every other control should usually have a \u0026lt;label\u0026gt; element pointing to it or wrapping it. If that's impossible, give it a \u003cb\u003etitle\u003c/b\u003e or \u003cb\u003eplaceholder\u003c/b\u003e attribute.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- Label separate from control. --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e    \u003cfont face\u003d\"'courier new', monospace\"\u003e\u0026lt;\u003cb\u003einput id\u003c/b\u003e\u003d\"developer_mode\" \u003cb\u003etype\u003c/b\u003e\u003d\"checkbox\"\u0026gt;\u003c/font\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e    \u003cfont face\u003d\"'courier new', monospace\"\u003e\u0026lt;\u003cb\u003elabel for\u003c/b\u003e\u003d\"developer_mode\"\u0026gt;Developer Mode\u0026lt;\u003cb\u003e/label\u003c/b\u003e\u0026gt;\u003c/font\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- Label wraps control (also valid). --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \u0026lt;\u003c/span\u003e\u003cb style\u003d\"font-family:courier new,monospace\"\u003elabel\u003c/b\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u0026gt;\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e    \u0026lt;\u003cb\u003einput\u003c/b\u003e \u003cb\u003etype\u003c/b\u003e\u003d\"checkbox\"\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e    Developer Mode\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u0026lt;\u003cb\u003e/label\u003c/b\u003e\u0026gt;\u003c/font\u003e\u003c/div\u003e\u003cdiv /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- Has placeholder. --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \u0026lt;\u003c/span\u003e\u003cb style\u003d\"font-family:courier new,monospace\"\u003einput\u003c/b\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e \u003cb\u003eplaceholder\u003c/b\u003e\u003d\"First name\"\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u0026gt;\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e  \u003cb style\u003d\"color:rgb(103,78,167)\"\u003e\u0026lt;!-- These need titles because the labels are implied for users who can see the screen.\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cb style\u003d\"color:rgb(103,78,167)\"\u003e       (Maybe a bad example, but hopefully you get the idea.) --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \u0026lt;\u003c/span\u003e\u003cb style\u003d\"font-family:courier new,monospace\"\u003einput\u003c/b\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e \u003cb\u003esize\u003d\"3\" title\u003c/b\u003e\u003d\"Area code\"\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u0026gt;\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \u0026lt;\u003c/span\u003e\u003cb style\u003d\"font-family:courier new,monospace\"\u003einput\u003c/b\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e \u003cb\u003esize\u003d\"3\" title\u003c/b\u003e\u003d\"Phone number (first 3 digits)\"\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u0026gt; -\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \u0026lt;\u003c/span\u003e\u003cb style\u003d\"font-family:courier new,monospace\"\u003einput\u003c/b\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e \u003cb\u003esize\u003d\"4\" title\u003c/b\u003e\u003d\"Phone number (last 4 digits)\"\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u0026gt;\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003eWhere necessary, override visible text with accessible text:\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003eOccasionally the text that's on the screen would be confusing to a blind user with a screen reader because the text is used symboically - for example an 'X' for a close button. In that case, using the title attribute won't work because the screen reader user will still also hear the 'X'. For this case, use aria-label.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eTry to avoid using aria-label when title or placeholder would work equally well.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cfont face\u003d\"'courier new', monospace\"\u003e\u003cb style\u003d\"color:rgb(103,78,167)\"\u003e  \u0026lt;!-- Uses aria-label to override the 'X' text and make sure Close is spoken instead. --\u0026gt;\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e  \u0026lt;\u003cb\u003ebutton aria-label\u003c/b\u003e\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u003d\"Close\"\u003c/span\u003e\u003cspan style\u003d\"font-family:courier new,monospace\"\u003e\u0026gt;X\u0026lt;\u003cb\u003e/button\u003c/b\u003e\u0026gt;\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003eNote that when it's an interactive control (like a button, checkbox, etc.) the aria-label attribute should go on the element that has focus.\u003c/div\u003e\u003cdiv\u003e\u003cb\u003e\u003cbr /\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7789018718369490338"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/accessibility/html-accessibility"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4942939941163791063"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4942939941163791063"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4942939941163791063"}],"author":[{"name":{"$t":"Dominic Mazzoni"},"email":{"$t":"dmazzoni@chromium.org"}}],"sites$pageName":{"$t":"html-accessibility"},"sites$revision":{"$t":"12"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2797343339804603652"},"published":{"$t":"2012-08-29T03:32:59.821Z"},"updated":{"$t":"2013-11-18T04:11:21.183Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:11:21.182Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Regression Detection for Performance Tests"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003eThis page describes the automated regression detection tool for ChromeOS performance tests. The tool is located at src/third_party/autotest/files/client/common_lib/perf_expectations.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-1.-Introduction\" /\u003e1. Introduction\u003c/h2\u003e\u003cdiv\u003e\u003cb\u003eperf_expectations.json \u003c/b\u003eis the place where perf expectations are specified. Each expectation is key-value pair. The key is formated as \"BOARD_NAME/TEST_NAME/TRACE_NAME\", for example, \"lumpy/desktopui_PyAutoPerfTests/FPS_ScrollTextPage\". The value is a dictionary like: {\"improve\":\"50.32\", \"regress\": \"43.23\", \"better\": \"lower\"}\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\"better\": the value for this field is \"lower\" or \"higher\", indicating whether\u003c/div\u003e\u003cdiv\u003e          this is a \"higher-is-better\" or \"lower-is-better\" case.\u003c/div\u003e\u003cdiv\u003e\"improve\": for \"higher-is-better\" case, if the actual perf value is higher than it, improvement is identified.\u003c/div\u003e\u003cdiv\u003e           for \"lower-is-better\" case, if the actual perf value is lower than it, improvement is identified.\u003c/div\u003e\u003cdiv\u003e\"regress\": for \"higher-is-better\" case, if the actual perf value is lower than it, regression is identified.\u003c/div\u003e\u003cdiv\u003e           for \"lower-is-better\" case, if the actual perf value is higher than it, regression is identified.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cb\u003eexpectation_checker.py \u003c/b\u003eprovides APIs that can be called at the end of a performance test. The checker compares actual performance values against expectations that are specified in perf_expectations.json.\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-2.-How-to-decide-the-baseline\" /\u003e2. How to decide the baseline\u003c/h2\u003e\u003cdiv\u003eCurrently, we need to manually figure out the values of \"improve\" and \"regress\" for each expectation. One strategy could be reasoning the baseline from a recent-look-good performance result. For example, for \"lumpy/desktopui_PyAutoPerfTests/FPS_ScrollTextPage\",\u003c/div\u003e\u003cdiv\u003ethe most recent result is 353.17. We decide to allow 15% tolerance. Then we can calculate the \"improve\" value as 353.17 * (1 + 0.15) \u003d 406.1455. Similarly, the \"regress\" value can be calculated as 353.17 * (1 - 0.15) \u003d 300.1945.\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-3.-How-to-modify-a-test-to-detect-regression.\" /\u003e3. How to modify a test to detect regression.\u003c/h2\u003e\u003cdiv\u003eAt the end of a performance test, initialize a perf_expectation_checker and then call perf_expectation_checker.compare_multiple_traces(...) to compare actual performance values with pre-defined expectations. By defaults, perf_expectations.json under the same folder of this file will be used.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eExample: \u003c/div\u003e\u003cdiv\u003e      At the end of 'src/third_party/autotest/files/client/site_test/desktopui_PyAutoPerfTests/desktopui_PyAutoPerfTests.py:run_once()', you can add the following code to detect regression/improvement:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      checker \u003d expectation_checker.perf_expectation_checker(\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e          \"desktopui_PyAutoPerfTests\")\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      result \u003d checker.compare_multiple_traces(perf_dict)\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      if result['regress']:\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e          raise error.TestFail('Pyauto perf tests regression detected: %s' %\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                               result['regress'])\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      if result['improve']:\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e          raise error.TestWarn('Pyauto perf tests improvement detected: %s' %\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e                               result['improve'])\u003c/code\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-4.-Notes\" /\u003e4. Notes\u003c/h2\u003e\u003cdiv\u003eThe idea of this tool is adopted from the automated regression detection tool for Chrome. Related information can be found at:\u003c/div\u003e\u003cdiv\u003ehttp://www.chromium.org/developers/tree-sheriffs/perf-sheriffs\u003c/div\u003e\u003cdiv\u003ehttp://src.chromium.org/viewvc/chrome/trunk/src/tools/perf_expectations\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eIdeally, the expectation checker should work the same way as the tool for Chrome. It currently has fewer features. In the future, like what Chrome team does, we can add a script, e.g. \"make_expectations.py\" which automatically reasons the thresholds values (\"improve\" and \"regress\") and update perf_expectations.json. We will need to add some additional fields in a expectation so that it will look like the following:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\"lumpy/desktopui_PyAutoPerfTests/FPS_ScrollTextPage\": \u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    {\"builda\": \"R23-2804.0.0\", \"buildb\": \"R23-2811.00\", \"improve\": \"50.32\", \"regress\": \"43.23\",\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e     \"better\": \"lower\", \"tolerance\":\"0.05\", \"sha1\": \"xd3234sdf32s\"}\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWhen we want to adjust the baseline, we will first figure out a build number range (builda, buildb) for which the performance results look good. Then we will run make_expectaions.py to automatically update the values of \"improve\" and \"regress\". Please refer to \u003c/div\u003e\u003cdiv\u003ehttp://src.chromium.org/viewvc/chrome/trunk/src/tools/perf_expectations/make_expectations.py to see how the idea is currently working for Chrome.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/perf-regression-detection"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2797343339804603652"},{"rel":"http://schemas.google.com/sites/2008#template","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7762381182101003415/2"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2797343339804603652"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2797343339804603652"}],"author":[{"name":{"$t":"Fang Deng"},"email":{"$t":"fdeng@chromium.org"}}],"sites$pageName":{"$t":"perf-regression-detection"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YDopeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3017762230154067281"},"published":{"$t":"2012-02-10T19:44:19.179Z"},"updated":{"$t":"2013-11-18T04:09:34.313Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:09:34.313Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Getting started with glmark2"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Introduction\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eIntroduction\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-What-is-OpenGL-ES-\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eWhat is OpenGL ES?\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-build-and-run-glmark2-on-your-Linux-machine\"\u003e\u003cstrong\u003e3 \u003c/strong\u003eHow to build and run glmark2 on your Linux machine\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-How-to-build-and-run-glmark2-in-Chromium-OS\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eHow to build and run glmark2 in Chromium OS\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Developing-for-glmark2\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eDeveloping for glmark2\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Introduction\" /\u003e\r\nIntroduction\u003c/h2\u003e\r\nThis guide describes how to download, modify, and \r\nbuild the glmark2 suite.  glmark2 is an OpenGL (ES) 2.0 benchmark \r\nmaintained by the Linaro Graphics Working group.  Their site is: \u003ca href\u003d\"https://launchpad.net/glmark2\" rel\u003d\"nofollow\"\u003ehttps://launchpad.net/glmark2\u003c/a\u003e\u003cbr /\u003e\u003cbr /\u003eThis guide is intended for anyone who wishes to use glmark2 in Chromium OS, as well as developers who wish to improve it.\u003cbr /\u003e\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-What-is-OpenGL-ES-\" /\u003eWhat is OpenGL ES?\u003c/h2\u003eOpenGL\r\n ES is a subset of the OpenGL API that is designed for embedded \r\nsystems.  It lacks many of the functions of OpenGL.  glmark2 supports \r\nboth regular OpenGL and OpenGL ES.\u003cbr /\u003e\u003cbr /\u003eRead more about it:\u003cbr /\u003e\u003ca href\u003d\"http://www.khronos.org/opengles\" rel\u003d\"nofollow\"\u003ehttp://www.khronos.org/opengles\u003c/a\u003e\u003cbr /\u003e\u003ca href\u003d\"http://en.wikipedia.org/wiki/OpenGL_ES\" rel\u003d\"nofollow\"\u003ehttp://en.wikipedia.org/wiki/OpenGL_ES\u003c/a\u003e\u003cbr /\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-build-and-run-glmark2-on-your-Linux-machine\" /\u003eHow to build and run glmark2 on your Linux machine\u003cbr /\u003e\u003c/h2\u003eBefore running it on Chromium OS, you might find it useful to run glmark2 on your Linux development workstation.  You can build glmark2 on a Linux workstation using the following steps:\u003cbr /\u003e\u003cbr /\u003eIn the terminal, go to a local folder and clone the upstream repo:\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\" style\u003d\"background-color:rgb(243,243,243)\"\u003e\u003cspan style\u003d\"color:rgb(0,0,0);font-family:sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;display:inline!important;float:none\"\u003e\u003ccode\u003egit clone git://git.linaro.org/people/afrantzis/glmark2.git\u003c/code\u003e\u003c/span\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ccode\u003ecd glmark2\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003eThe instructions to build and install are in the INSTALL file.  You can reference that or follow these instructions:\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003esudo -i\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e# install as root\u003cbr /\u003e\u003cbr /\u003e./waf configure --enable-gl\u003cspan\u003e    \u003c/span\u003e# setup for installing glmark2 with regular OpenGL\u003cbr /\u003e\u003cbr /\u003e./waf\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e  # build it!\u003cbr /\u003e\u003cbr /\u003e./waf install\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e    \u003c/span\u003e\u003cspan\u003e  \u003c/span\u003e# installs files into /usr/local/bin and /usr/local/share/glmark2\u003cbr /\u003e\u003c/span\u003e\u003c/code\u003e\u003c/div\u003e\u003cp\u003eOnce installed, run glmark2 using the command:\u003c/p\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eglmark2\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-How-to-build-and-run-glmark2-in-Chromium-OS\" /\u003eHow to build and run glmark2 in Chromium OS\u003c/h2\u003eglmark2 has been incorporated into Chromium OS as a third party git repository, so it can be built using emerge.\u003cbr /\u003e\u003cbr /\u003eglmark2 depends on mesa.  First, you need to build mesa with the following command:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eUSE\u003d\"egl gbm gles1 gles2 shared-glapi\" emerge-\u0026lt;board\u0026gt; mesa\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003e**Temporary workaround step: Save the glmark2 ebuild file that's attached to this page (see below) into third_party/chromiumos-overlay/media-libs/glmark2.\u003cbr /\u003e\u003cbr /\u003eThen build glmark2 using:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eUSE\u003d\"glesv2 drm\" emerge-\u0026lt;board\u0026gt; glmark2\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003eWhen this done, install it on your Chromium OS target machine.  From the target machine, run:\u003cbr /\u003e\u003cbr /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003egmerge -n mesa\u003cbr /\u003e\u003cbr /\u003egmerge -n glmark2\u003c/code\u003e\u003c/div\u003e\u003cbr /\u003eOnce it has been installed, run glmark2 with one of the following commands:\u003cbr /\u003e\r\n\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003ccode\u003eglmark2                    # with OpenGL\u003c/code\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ccode\u003e\r\nglmark2-es2                # with OpenGL ES v2\u003c/code\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ccode\u003e\r\nglmark2-es2-drm            # with OpenGL ES v2 and without X\u003c/code\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Developing-for-glmark2\" /\u003eDeveloping for glmark2\u003c/h2\u003eIn your Chromium OS development chroot, go to\u003cspan style\u003d\"font-family:courier new,monospace;color:rgb(0,0,0)\"\u003e \u003c/span\u003e\u003ccode style\u003d\"font-family:courier new,monospace;color:rgb(68,68,68)\"\u003e~/trunk/src/third_party/glmark2\u003c/code\u003e.  You can modify the source code here.  To change build options, update \u003cspan style\u003d\"font-family:courier new,monospace;color:rgb(68,68,68)\"\u003ethird_party/chromiumos-overlay/media-libs/glmark2/glmark2-9999.ebuild\u003c/span\u003e.\u003cbr /\u003e\u003cbr /\u003eOnce your changes are up and running, you can send them upstream.\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/593897542665142458"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/getting-started-with-glmark2"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3017762230154067281"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3017762230154067281"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3017762230154067281"}],"author":[{"name":{"$t":"Simon Que"},"email":{"$t":"sque@chromium.org"}}],"sites$pageName":{"$t":"getting-started-with-glmark2"},"sites$revision":{"$t":"6"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8723633024987169022"},"published":{"$t":"2012-03-09T05:02:25.616Z"},"updated":{"$t":"2013-11-18T04:09:34.309Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2012-03-09T05:02:25.616Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"glmark2-9999.ebuild"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8723633024987169022"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3017762230154067281"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/getting-started-with-glmark2/glmark2-9999.ebuild"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8723633024987169022"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8723633024987169022"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8723633024987169022"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8723633024987169022"}],"author":[{"name":{"$t":"Simon Que"},"email":{"$t":"sque@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8512025493168932627"},"published":{"$t":"2013-10-16T17:51:48.730Z"},"updated":{"$t":"2013-11-18T04:08:02.046Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:08:02.046Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Writing multiprocess programs in Python"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003eThe \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/chromite/+/HEAD/lib/parallel.py\"\u003echromite.lib.parallel\u003c/a\u003e module is the preferred way to write multiprocess python programs in Chrome OS.\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003eIt offers the following advantages over the multiprocessing module:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cul\u003e\u003cli\u003eThe multiprocessing module can be buggy, so it is difficult to avoid hangs without substantial trial and error figuring out what features of multiprocessing actually work. We have already done this for you in the parallel library.\u003cbr /\u003e\u003c/li\u003e\u003cli\u003eThe interface for the parallel library is simpler than the multiprocessing interface and performs tasks that you would need to perform manually if you were using multiprocessing.\u003c/li\u003e\u003cli\u003eThe parallel library automatically queues up output in temporary files and prints them out serially. This means that you never need to worry about interleaved output.\u003c/li\u003e\u003cli\u003eThe parallel library handles cases where the subprocess hangs and prints out suitable errors.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003eHere's the \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/chromite/+/HEAD/lib/parallel.py\"\u003echromite.lib.parallel\u003c/a\u003e function for running multiple steps in parallel in a very simple way. The docstring should help explain how it works.\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003edef RunParallelSteps(steps, max_parallel\u003dNone, halt_on_error\u003dFalse,                                                                     \u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e                     return_values\u003dFalse):\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \"\"\"Run a list of functions in parallel.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  This function blocks until all steps are completed.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  The output from the functions is saved to a temporary file and printed as if\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  they were run in sequence.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  If exceptions occur in the steps, we join together the tracebacks and print\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  them after all parallel tasks have finished running. Further, a\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  BackgroundFailure is raised with full stack traces of all exceptions.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Args:\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    steps: A list of functions to run.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    max_parallel: The maximum number of simultaneous tasks to run in parallel.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e      By default, run all tasks in parallel.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    halt_on_error: After the first exception occurs, halt any running steps,\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e      and squelch any further output, including any exceptions that might occur.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    return_values: If set to True, RunParallelSteps returns a list containing\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e      the return values of the steps.  Defaults to False.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Returns:\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    If |return_values| is True, the function will return a list containing the\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    return values of the steps.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  Example:\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    # This snippet will execute in parallel:\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    #   somefunc()\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    #   anotherfunc()\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    #   funcfunc()\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    steps \u003d [somefunc, anotherfunc, funcfunc]\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    RunParallelSteps(steps)\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e    # Blocks until all calls have completed.\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e  \"\"\"\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003eIf you want to be able to use a worker-based model and push items to the subprocess one by one, the BackgroundTaskRunner will do the job:\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial;font-size:small\"\u003e\u003cfont face\u003d\"courier new, monospace\"\u003e\u003cdiv\u003e@contextlib.contextmanager\u003c/div\u003e\u003cdiv\u003edef BackgroundTaskRunner(task, *args, **kwargs):\u003c/div\u003e\u003cdiv\u003e  \"\"\"Run the specified task on each queued input in a pool of processes.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  This context manager starts a set of workers in the background, who each\u003c/div\u003e\u003cdiv\u003e  wait for input on the specified queue. For each input on the queue, these\u003c/div\u003e\u003cdiv\u003e  workers run task(*args + *input, **kwargs). Note that certain kwargs will\u003c/div\u003e\u003cdiv\u003e  not pass through to the task (see Args below for the list).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  The output from these tasks is saved to a temporary file. When control\u003c/div\u003e\u003cdiv\u003e  returns to the context manager, the background output is printed in order,\u003c/div\u003e\u003cdiv\u003e  as if the tasks were run in sequence.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  If exceptions occur in the steps, we join together the tracebacks and print\u003c/div\u003e\u003cdiv\u003e  them after all parallel tasks have finished running. Further, a\u003c/div\u003e\u003cdiv\u003e  BackgroundFailure is raised with full stack traces of all exceptions.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  Example:\u003c/div\u003e\u003cdiv\u003e    # This will run somefunc(1, 'small', 'cow', foo\u003d'bar') in the background\u003c/div\u003e\u003cdiv\u003e    # as soon as data is added to the queue (i.e. queue.put() is called).\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e    def somefunc(arg1, arg2, arg3, foo\u003dNone):\u003c/div\u003e\u003cdiv\u003e      ...\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e    with BackgroundTaskRunner(somefunc, 1, foo\u003d'bar') as queue:\u003c/div\u003e\u003cdiv\u003e      ... do random stuff ...\u003c/div\u003e\u003cdiv\u003e      queue.put(['small', 'cow'])\u003c/div\u003e\u003cdiv\u003e      ... do more random stuff while somefunc() runs ...\u003c/div\u003e\u003cdiv\u003e    # Exiting the with statement will block until all calls have completed.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e  Args:\u003c/div\u003e\u003cdiv\u003e    task: Function to run on each queued input.\u003c/div\u003e\u003cdiv\u003e    queue: A queue of tasks to run. Add tasks to this queue, and they will\u003c/div\u003e\u003cdiv\u003e      be run in the background.  If None, one will be created on the fly.\u003c/div\u003e\u003cdiv\u003e    processes: Number of processes to launch.\u003c/div\u003e\u003cdiv\u003e    onexit: Function to run in each background process after all inputs are\u003c/div\u003e\u003cdiv\u003e      processed.\u003c/div\u003e\u003cdiv\u003e  \"\"\"\u003c/div\u003e\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8945126227284375934"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/build/chromite-parallel"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8512025493168932627"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8512025493168932627"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8512025493168932627"}],"author":[{"name":{"$t":"David James"},"email":{"$t":"davidjames@chromium.org"}}],"sites$pageName":{"$t":"chromite-parallel"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDQpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"},"published":{"$t":"2008-10-21T20:42:15.851Z"},"updated":{"$t":"2013-11-18T04:07:38.006Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:07:38.005Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Web page views"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eOur original architecture did not have any platform separation in the browser window and tab layer. WebContents contained a RenderViewHost, and that implemented a great deal of both logic and view-related functionality.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eWe want to make this architecture cleaner and separate out the view from the cross-platform logic. This document tracks the progress of this work.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Current-architecture\" /\u003eCurrent architecture\u003c/h2\u003e\u003cdiv\u003eWe have split out a variety of OS-specific views from WebContents. On Windows, the objects look like this:\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;margin-right:auto;margin-left:auto;text-align:center\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/Web-page-views/WebContents3.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1384747658000/developers/Web-page-views/WebContents3.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eThe view-related calls from RenderViewHost to WebContentsView are removed from WebContents completely by using a separate delegate. When RenderViewHost needs to make a view-related call, it asks its delegate (through the RenderViewHostDelegate interface) for the \"View\" delegate. This is implemented by the WebContentsView.\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/Web-page-views"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6575422492342253088"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"}],"author":[{"name":{"$t":"Brett Wilson"},"email":{"$t":"brettw@chromium.org"}}],"sites$pageName":{"$t":"Web-page-views"},"sites$revision":{"$t":"8"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3817650679360052544"},"published":{"$t":"2008-10-22T15:02:31.054Z"},"updated":{"$t":"2013-11-18T04:07:38.000Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2008-10-22T15:02:31.054Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"WebContents3.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3817650679360052544"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/Web-page-views/WebContents3.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3817650679360052544"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3817650679360052544"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3817650679360052544"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3817650679360052544"}],"author":[{"name":{"$t":"Brett Wilson"},"email":{"$t":"brettw@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4680720536801698234"},"published":{"$t":"2008-10-21T21:12:17.856Z"},"updated":{"$t":"2013-11-18T04:07:38.000Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2008-10-21T21:12:17.856Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"WebContents2.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4680720536801698234"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/Web-page-views/WebContents2.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4680720536801698234"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4680720536801698234"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4680720536801698234"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4680720536801698234"}],"author":[{"name":{"$t":"Brett Wilson"},"email":{"$t":"brettw@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/332926593126106282"},"published":{"$t":"2008-10-21T20:45:06.905Z"},"updated":{"$t":"2013-11-18T04:07:37.999Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2008-10-21T21:11:40.049Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"WebContents.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/332926593126106282"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/Web-page-views/WebContents.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/332926593126106282"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/332926593126106282"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/332926593126106282"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/332926593126106282"}],"author":[{"name":{"$t":"Brett Wilson"},"email":{"$t":"brettw@chromium.org"}}],"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1524248692838972630"},"published":{"$t":"2008-10-21T20:45:22.468Z"},"updated":{"$t":"2013-11-18T04:07:37.999Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2008-10-22T15:02:52.073Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"WebContents.graffle"},"summary":{},"content":{"type":"application/octet-stream","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/1524248692838972630"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6575422492342253088"},{"rel":"alternate","type":"application/octet-stream","href":"https://sites.google.com/a/chromium.org/dev/developers/Web-page-views/WebContents.graffle"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1524248692838972630"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1524248692838972630"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1524248692838972630"},{"rel":"edit-media","type":"application/octet-stream","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/1524248692838972630"}],"author":[{"name":{"$t":"Brett Wilson"},"email":{"$t":"brettw@chromium.org"}}],"sites$revision":{"$t":"4"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1601298339708489336"},"published":{"$t":"2013-11-13T22:46:10.702Z"},"updated":{"$t":"2013-11-18T04:02:38.456Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:02:38.456Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"chroot_version_hooks"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-Summary\" /\u003eSummary\u003c/h3\u003eOn occasion changes are made to some component of the Chromium OS source that are not backwards-compatible with existing chroots.  When this happens a \"chroot version hook\" should be used to make whatever changes are necessary to an existing chroot to make it compatible.  Usually this involves deleting some previously compiled/generated component in order to force it to be compiled/generated again.\u003ch3\u003e\u003ca name\u003d\"TOC-Details\" /\u003eDetails\u003c/h3\u003e\u003cdiv\u003eThe version hooks all exist under \u003ca href\u003d\"https://chromium.googlesource.com/chromiumos/platform/crosutils/+/master/chroot_version_hooks.d/\"\u003esrc/scripts/chroot_version_hooks.d\u003c/a\u003e.  Each hook script has a name that begins with \"\u0026lt;num\u0026gt;_\", where \u0026lt;num\u0026gt; is an integer that represents the version number of a chroot.  Whenever a new chroot is entered (via \"cros_sdk\") or \"build_packages\" is run all upgrade hooks with versions newer than the chroot version are run (in sequential order) to upgrade the chroot to the latest version.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eUpgrade scripts can be arbitrary bash scripts.  The best way to write a new script is to look for existing examples in chroot_version_hooks.d.  With that said, the following example hook script will delete the build roots for all boards and all Chrome artifacts.  This is needed, for example, when a toolchain uprev needs to be reverted.  Everything built with the newer (bad) toolchain must be deleted.\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv /\u003e\u003cdiv class\u003d\"sites-codeblock sites-codesnippet-block\"\u003e\u003cdiv\u003e\u003ccode\u003e# This is to clear the build roots for all boards to cope with a\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e# toolchain revert.\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003efor board_root in /build/* ; do\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  board\u003d${board_root##*/}\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  emerge_board\u003d$(type -P emerge-${board} 2\u0026gt;/dev/null || true)\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  if [[ -x \"${emerge_board}\" ]]; then\u003c/code\u003e\u003cspan style\u003d\"white-space:pre\"\u003e\t\u003c/span\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    # It is a valid baord.\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    build\u003d\"/build/${board}\"\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    if [[ -d ${build} ]] ; then\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      # The board has a build root to clear.\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      info \"Deleting ${board} build root at ${build}\"\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      sudo rm -rf ${build}\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      info \"Running setup_board --board\u003d${board}\"\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e      ~/trunk/src/scripts/setup_board --board\u003d${board} --skip_chroot_upgrade\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e    fi\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e  fi\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003edone\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e\u003cbr /\u003e\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003e# Delete Chrome artifacts\u003c/code\u003e\u003c/div\u003e\u003cdiv\u003e\u003ccode\u003esudo rm -rf /var/cache/chromeos-chrome/* || true\u003c/code\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8945126227284375934"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/build/chroot_version_hooks"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1601298339708489336"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1601298339708489336"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1601298339708489336"}],"author":[{}],"sites$pageName":{"$t":"chroot_version_hooks"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/9189444673294352848"},"published":{"$t":"2012-03-07T16:49:07.283Z"},"updated":{"$t":"2013-11-18T04:00:36.495Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T04:00:36.495Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"pydevi2c"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003ePlaceholder page for pydevi2c (python bindings for talking to /dev/i2c devices).\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eSee: http://git.chromium.org/gitweb/?p\u003dchromiumos/platform/pydevi2c.git\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7575192847733958161"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/packages/pydevi2c"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/9189444673294352848"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9189444673294352848"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9189444673294352848"}],"author":[{"name":{"$t":"Douglas Anderson"},"email":{"$t":"dianders@chromium.org"}}],"sites$pageName":{"$t":"pydevi2c"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YDgpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1876598440749967716"},"published":{"$t":"2011-02-16T19:29:52.940Z"},"updated":{"$t":"2013-11-18T03:58:06.122Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T03:58:06.122Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Cellular: Testing"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eThe cellular team uses autotests for end-to-end testing of the cellular components. There are a few separate suites:\u003cbr /\u003e\u003col\u003e\u003cli\u003esuite_Cellular: You should run this before pushing a CL that affects part of the cellular stack. Tests here can run on real hardware and shouldn't take too long.\u003cbr /\u003e\u003c/li\u003e\u003cli\u003econtrol.network_3g: This is what the hardware test lab runs \"every so often\". This runs on real hardware and can take a long time if needed.\u003cbr /\u003e\u003c/li\u003e\u003cli\u003eBVT (the build verify test): runs nothing (yet). We need to fix this by making some of our tests appropriate for running in a VM. This should run quickly.\u003cbr /\u003e\u003c/li\u003e\u003c/ol\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3327849403326279945"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/testing/cellular-testing"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1876598440749967716"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1876598440749967716"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1876598440749967716"}],"author":[{"name":{"$t":"Elly Fong-Jones"},"email":{"$t":"ellyjones@chromium.org"}}],"sites$pageName":{"$t":"cellular-testing"},"sites$revision":{"$t":"4"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8467192152453700693"},"published":{"$t":"2010-04-02T20:20:53.835Z"},"updated":{"$t":"2013-11-18T03:56:39.241Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-04-02T20:20:53.835Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"diagmode_wiki.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8467192152453700693"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1255861932095370200"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/diagnostic-mode/diagmode_wiki.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8467192152453700693"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8467192152453700693"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8467192152453700693"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8467192152453700693"}],"author":[{"name":{"$t":"Carlos Pizano"},"email":{"$t":"cpu@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD8peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4078144862582799978"},"published":{"$t":"2010-12-10T00:07:53.629Z"},"updated":{"$t":"2013-11-18T03:56:28.333Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T03:56:28.333Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"ESET Anti-Virus"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eSome home security / anti-virus software can interact badly with Chrome. If you have been directed here you may need to configure your anti-virus software to allow Chrome to access the Internet.\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv\u003e\u003cb\u003eESET Smart Security\u003c/b\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003eUnder `Setup’ click `Toggle Advanced mode’:\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception/1.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1384746988304/administrators/err_eset_anti_virus_ssl_interception/1.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003eOnce in advanced mode, click `Enter entire advanced setup tree’:\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception/2.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1384746988304/administrators/err_eset_anti_virus_ssl_interception/2.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:transparent;font-family:Times New Roman;font-size:medium\"\u003e\u003cspan style\u003d\"font-size:11pt;font-family:Arial;color:rgb(0,0,0);background-color:transparent;font-weight:normal;font-style:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap\"\u003eFind `SSL’ under `Protocol filtering’ and select `Do not scan SSL protocol’:\u003c/span\u003e\u003c/div\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception/3.png?attredirects\u003d0\" imageanchor\u003d\"1\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1384746988304/administrators/err_eset_anti_virus_ssl_interception/3.png\" /\u003e\u003c/a\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003cbr /\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7817060016656641064"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4078144862582799978"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4078144862582799978"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4078144862582799978"}],"author":[{"name":{"$t":"Adam Langley"},"email":{"$t":"agl@chromium.org"}}],"sites$pageName":{"$t":"err_eset_anti_virus_ssl_interception"},"sites$revision":{"$t":"3"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2694627774381858922"},"published":{"$t":"2010-12-10T00:12:55.991Z"},"updated":{"$t":"2013-11-18T03:56:28.304Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-12-10T00:12:55.991Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"3.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2694627774381858922"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4078144862582799978"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception/3.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2694627774381858922"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2694627774381858922"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2694627774381858922"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2694627774381858922"}],"author":[{"name":{"$t":"Adam Langley"},"email":{"$t":"agl@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3148467989777942080"},"published":{"$t":"2010-12-10T00:11:28.326Z"},"updated":{"$t":"2013-11-18T03:56:28.304Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-12-10T00:11:28.326Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"2.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3148467989777942080"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4078144862582799978"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception/2.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3148467989777942080"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3148467989777942080"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3148467989777942080"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3148467989777942080"}],"author":[{"name":{"$t":"Adam Langley"},"email":{"$t":"agl@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YD4peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5217118629750850118"},"published":{"$t":"2010-12-10T00:10:21.641Z"},"updated":{"$t":"2013-11-18T03:56:28.304Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2010-12-10T00:10:21.641Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"1.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5217118629750850118"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4078144862582799978"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/administrators/err_eset_anti_virus_ssl_interception/1.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5217118629750850118"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5217118629750850118"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5217118629750850118"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5217118629750850118"}],"author":[{"name":{"$t":"Adam Langley"},"email":{"$t":"agl@chromium.org"}}],"sites$revision":{"$t":"2"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2630438300839711033"},"published":{"$t":"2013-01-25T23:41:40.216Z"},"updated":{"$t":"2013-11-18T03:53:54.575Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-18T03:53:54.574Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Finding somebody who knows how a piece of code works"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cb style\u003d\"font-family:Times New Roman;font-weight:normal\"\u003e\u003cspan style\u003d\"font-family:Arial;background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003e\u003cfont size\u003d\"2\"\u003eIt’s much more efficient to ask somebody how something works than to take weeks to figure it out yourself.  So how do you find the person who knows how it works?  Here are some ideas to get you started.\u003c/font\u003e\u003c/span\u003e\u003c/b\u003e\u003cdiv\u003e\u003cb style\u003d\"font-weight:normal\"\u003e\u003cfont size\u003d\"2\"\u003e\u003cfont face\u003d\"Arial\"\u003e\u003cspan style\u003d\"white-space:pre-wrap\"\u003e\u003cbr /\u003e\u003c/span\u003e\u003c/font\u003e\u003col style\u003d\"font-family:Times New Roman;margin-top:0pt;margin-bottom:0pt\"\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eAsk your teammates - the folks who have been on the project longer than you will have a better idea or may have contacts in other areas.  \u003c/span\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eLook at the OWNERS files - If you can identify a source file involved in what you want to do, find the lowest level OWNERS file above it, and email those people.  Be aware that they may no longer be working on chromium, or on parental leave, so don’t just wait forever and keep hoping for an answer if you don’t hear back soon.\u003c/span\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eSometimes, there isn't one person who knows what you want to find out, but you can find people who know parts of the system.  For instance, no one person knows everything about how chromium starts up or shuts down and can tell you what you did wrong in a shutdown scenario, but you can find people who know some parts of the shutdown to guide you.\u003c/span\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eUse the IRC channel - while not everybody is listening all the time, there is always a sheriff listening, and you may get a pointer to the right folks to talk to.\u003c/span\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eUse the chromium-dev email alias to ask questions.  This is a fairly large email list, so use your judgment about what to post, and it may take awhile to get a reply.  If you do this, it helps to ask one crisp question at the top of your mail and then explain in detail instead of rambling and asking many questions.\u003c/span\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eTry searching the code.  Sure, searching for “Init” or “setup” will have about 10^100 hits (at least it will seem that way), but searching for something more specific may pay off.  Try several related terms.  For instance, searching for “favicon” will quickly take you to the right part of the code, even if you have no idea how the code is laid out our what you are looking at when you arrive at the right code.\u003c/span\u003e\u003c/li\u003e\u003cli dir\u003d\"ltr\" style\u003d\"list-style-type:decimal;font-family:Arial;background-color:transparent;vertical-align:baseline\"\u003e\u003cspan style\u003d\"background-color:transparent;vertical-align:baseline;white-space:pre-wrap\"\u003eDebugging into the code can provide a lot of insight.\u003c/span\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/685187476307440333"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/finding-somebody-who-knows-how-a-piece-of-code-works"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2630438300839711033"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2630438300839711033"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2630438300839711033"}],"author":[{"name":{"$t":"Peter Williamson"},"email":{"$t":"petewil@chromium.org"}}],"sites$pageName":{"$t":"finding-somebody-who-knows-how-a-piece-of-code-works"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"XSl7JmA4\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8906149681394230569"},"published":{"$t":"2011-07-27T07:48:30.955Z"},"updated":{"$t":"2013-11-12T18:24:59.920Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-12T18:24:58.138Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"PNaCl Bitcode Reference Manual"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003eSee \u003ca href\u003d\"https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi\"\u003ehttps://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi\u003c/a\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2062405729464790262"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/bitcode-abi"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8906149681394230569"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8906149681394230569"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8906149681394230569"}],"author":[{}],"sites$pageName":{"$t":"bitcode-abi"},"sites$revision":{"$t":"44"}},{"gd$etag":"\"YDkpeyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5062187655050566100"},"published":{"$t":"2009-11-19T17:03:00.356Z"},"updated":{"$t":"2013-11-08T22:13:52.822Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2011-07-29T23:21:35.723Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"File System/Autoupdate"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv class\u003d\"sites-embed-align-right-wrapping-on\"\u003e\u003cdiv class\u003d\"sites-embed-border-off sites-embed\" style\u003d\"width:250px;\"\u003e\u003cdiv class\u003d\"sites-embed-content sites-embed-type-toc\"\u003e\u003cdiv class\u003d\"goog-toc sites-embed-toc-maxdepth-6\"\u003e\u003cp\u003eContents\u003c/p\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Abstract\"\u003e\u003cstrong\u003e1 \u003c/strong\u003eAbstract\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Goals\"\u003e\u003cstrong\u003e2 \u003c/strong\u003eGoals\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Partitions\"\u003e\u003cstrong\u003e3 \u003c/strong\u003ePartitions\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Root-file-system\"\u003e\u003cstrong\u003e3.1 \u003c/strong\u003eRoot file system\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-The-update-process\"\u003e\u003cstrong\u003e4 \u003c/strong\u003eThe update process\u003c/a\u003e\u003col class\u003d\"goog-toc\"\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Successful-boot\"\u003e\u003cstrong\u003e4.1 \u003c/strong\u003eSuccessful boot\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Limiting-the-number-of-boot-attempt\"\u003e\u003cstrong\u003e4.2 \u003c/strong\u003eLimiting the number of boot attempts\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Diagram\"\u003e\u003cstrong\u003e4.3 \u003c/strong\u003eDiagram\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Supplements\"\u003e\u003cstrong\u003e5 \u003c/strong\u003eSupplements\u003c/a\u003e\u003c/li\u003e\u003cli class\u003d\"goog-toc\"\u003e\u003ca href\u003d\"#TOC-Other-notes\"\u003e\u003cstrong\u003e6 \u003c/strong\u003eOther notes\u003c/a\u003e\u003c/li\u003e\u003c/ol\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Abstract\" /\u003eAbstract\u003c/h2\u003e\r\nThis document describes the Chromium OS file system and the autoupdate system.\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003eWe expect regular updates to Chromium OS to add new functionality, improve system performance, and enhance the user experience. \u003c/li\u003e\r\n\u003cli\u003e\r\nThe autoupdate mechanism aims to provide seamless and secure updates to the latest version of Chromium OS. No user interaction is required. \u003c/li\u003e\r\n\u003cli\u003e\r\nUpdates usually come in the form of deltas (i.e. only the parts of the system that changed are downloaded) which are downloaded to a backup boot partition. Upon reboot, the backup partition becomes the primary.\u003c/li\u003e\r\n\u003cli\u003e\r\nIn case there is a problem with the update, the system can revert to using the previous partition. \u003c/li\u003e\r\n\u003cli\u003e\r\nOne way in which we secure Chromium OS is by keeping the partition containing the OS and other system files read-only. All temporary user state (such as browser caches, cookies, etc) is stored on a separate partition. \u003c/li\u003e\u003c/ul\u003e\r\n\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Goals\" /\u003eGoals\u003c/h2\u003e\r\nThe autoupdate system has the following goals:\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eUpdates are delta-compressed over the wire.\u003c/li\u003e\r\n\u003cli\u003eDelta updates are quick to apply.\u003c/li\u003e\r\n\u003cli\u003eRoot file system is mounted read-only (another mount point is read/write for storing state).\u003c/li\u003e\r\n\u003cli\u003eDevice can automatically revert to previous installed version of the OS if the newly installed OS fails to boot properly.\u003c/li\u003e\r\n\u003cli\u003eUpdates are automatic and silent.\u003c/li\u003e\r\n\u003cli\u003eUpdates should be small.\u003c/li\u003e\r\n\u003cli\u003eSystem protects users from security exploits.\u003c/li\u003e\r\n\u003cli\u003eSystem never requires more than one reboot for an update.\u003c/li\u003e\r\n\u003cli\u003eThere's a clear division between the storage locations on the drive for system software and for user data.\u003c/li\u003e\r\n\u003cli\u003eThe new update must be set bit-for-bit from the server, since we will be signing each physical block on the system partition. (For more information, see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot\"\u003eVerified Boot\u003c/a\u003e design document.)\u003cbr /\u003e\r\n\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Partitions\" /\u003ePartitions\u003c/h2\u003e\r\nA drive currently contains at least these partitions:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003eOne\r\npartition for state resident on the drive (user's home directory/Chromium profile,\r\nlogs, etc.)—called the \"stateful partition.\"\u003c/li\u003e\r\n\u003cli\u003eTwo partitions for the root file system.\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Root-file-system\" /\u003eRoot file system\u003c/h3\u003e\r\nOnly\r\none of the two partitions designated for the root file system will be in\r\nuse at a given time. The other will be used for autoupdating and for a fallback if the current partition fails to boot.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nWhile a partition is in\r\nuse as the boot partition, it's read-only until the\r\nnext boot. Not even the autoupdater will edit the currently-booted root\r\nfile system. We will mount the stateful partition read-write and use\r\nthat for all state that needs to be stored locally.\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eDuring\r\nautoupdate, we will write to the other system partition. Only the updater (and apps running as root) will\r\nhave access to that partition.\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-The-update-process\" /\u003e\u003cb\u003eThe update process\u003c/b\u003e\u003c/h2\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Successful-boot\" /\u003eSuccessful boot\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eThe update process relies partly on the concept of a \"successful boot.\" At any\r\ngiven point, we will be able to say one of the following things:\u003cbr /\u003e\r\n\u003cul\u003e\u003cli\u003eThis system booted up correctly.\u003c/li\u003e\r\n\u003cli\u003eThis system booted up incorrectly.\u003c/li\u003e\r\n\u003cli\u003eThe system is currently attempting to boot, so we don't know yet.\u003c/li\u003e\u003c/ul\u003e\r\nWe consider a boot successful if the updater process can successfully launch.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nOnce a system has booted successfully, we consider the\r\nother root partition to be available for overwriting with an autoupdate.\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Limiting-the-number-of-boot-attempt\" /\u003eLimiting the number of boot attempts\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003eAn updated partition can attempt to boot only a limited number of times; if it doesn't boot successfully after a couple of attempts, then the system goes back to booting from the other partition. The number of attempts is limited as follows:\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nWhen a partition has successfully been updated, it's assigned a remaining_attempts value, currently 6. This\r\nvalue will be stored in the partition table next to the bootable flag (there\r\nare unused bits in the GPT that the boot loader can use for its own\r\npurposes). The boot loader will examine all partitions in the system; if it finds any partition that has a remaining_attempts value\r\n\u0026gt; 0, it\r\nwill decrement remaining_attempts and then attempt to boot from that partition. If the boot fails, then this process repeats.\u003cbr /\u003e\r\n\u003cbr /\u003e\r\nIf no partitions have a\r\nremaining_attempts value \u0026gt; 0, the boot loader will boot from a partition marked\r\nbootable, as a traditional boot loader would.\u003cbr /\u003e\r\n\u003ch3\u003e\u003ca name\u003d\"TOC-Diagram\" /\u003eDiagram\u003c/h3\u003e\r\nHere's a diagram of the boot process:\u003cfont color\u003d\"#ff0000\"\u003e\u003cbr /\u003e\u003c/font\u003e\r\n\u003cdiv style\u003d\"display:block;text-align:left\"\u003e\u003cimg border\u003d\"0\" src\u003d\"https://sites.google.com/a/chromium.org/dev/_/rsrc/1311980716766/chromium-os/chromiumos-design-docs/filesystem-autoupdate/ChromeOSFilesystemAutoupdate.png\" /\u003e\u003c/div\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Supplements\" /\u003eSupplements\u003c/h2\u003eFor a detailed design into how delta updates are generated and applied, see: \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/autoupdate-details\"\u003eAutoupdate Details\u003c/a\u003e.\u003cbr /\u003e\u003cbr /\u003e\r\nFor supplementary information about related material, see the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/filesystem-autoupdate-supplements\"\u003eFilesystem/Autoupdate supplements\u003c/a\u003e document.\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003ch2\u003e\u003ca name\u003d\"TOC-Other-notes\" /\u003e\u003cb\u003eOther notes\u003c/b\u003e\u003c/h2\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003eAll updates directly overwrite the new partition and require no temporary space.\u003c/li\u003e\r\n\u003cli\u003eWe\r\ndownload the update over HTTPS, requiring a server certificate signed\r\nby the one Certification Authority that issues OS provider's SSL\r\ncertificates.\u003c/li\u003e\r\n\u003cli\u003eUpdates are hashed and checksummed. The update servers may sign updates as well.\u003c/li\u003e\u003c/ul\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cbr /\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3366051319303255070"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/filesystem-autoupdate"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5062187655050566100"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5062187655050566100"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5062187655050566100"}],"author":[{}],"sites$pageName":{"$t":"filesystem-autoupdate"},"sites$revision":{"$t":"5"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/229362227709083917"},"published":{"$t":"2013-11-08T20:11:47.070Z"},"updated":{"$t":"2013-11-08T20:11:47.132Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-08T20:11:47.070Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"net-internals.PNG"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/229362227709083917"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7356854172176759459"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/for-testers/providing-network-details/net-internals.PNG"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/229362227709083917"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/229362227709083917"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/229362227709083917"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/229362227709083917"}],"author":[{"name":{"$t":"Ricardo Vargas"},"email":{"$t":"rvargas@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5054280085809664134"},"published":{"$t":"2013-11-03T15:38:01.772Z"},"updated":{"$t":"2013-11-03T15:38:01.818Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-11-03T15:38:01.772Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"SheriffBadge2.jpg"},"summary":{},"content":{"type":"image/jpeg","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5054280085809664134"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4727746233434872159"},{"rel":"alternate","type":"image/jpeg","href":"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/perf-sheriffs/SheriffBadge2.jpg"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5054280085809664134"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5054280085809664134"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5054280085809664134"},{"rel":"edit-media","type":"image/jpeg","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5054280085809664134"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5673011541818539876"},"published":{"$t":"2013-10-29T14:49:13.577Z"},"updated":{"$t":"2013-10-29T14:49:14.333Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-29T14:49:13.577Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 29 2013 07:49:13 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003ehartmanng\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-29-2013-07-49-13-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5673011541818539876"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5673011541818539876"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5673011541818539876"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-29-2013-07-49-13-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2349207565514482240"},"published":{"$t":"2013-10-29T03:36:10.712Z"},"updated":{"$t":"2013-10-29T03:36:10.765Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-29T03:36:10.712Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"printto-workaround.cpp"},"summary":{},"content":{"type":"text/x-c++src","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2349207565514482240"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1172975616400693679"},{"rel":"alternate","type":"text/x-c++src","href":"https://sites.google.com/a/chromium.org/dev/blink/unittesting/printto-workaround.cpp"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2349207565514482240"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2349207565514482240"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2349207565514482240"},{"rel":"edit-media","type":"text/x-c++src","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2349207565514482240"}],"author":[{"name":{"$t":"Tim Ansell"},"email":{"$t":"tansell@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2985333278952154103"},"published":{"$t":"2013-10-29T01:11:18.266Z"},"updated":{"$t":"2013-10-29T01:11:18.489Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-29T01:11:18.266Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"printto-confusing.cpp"},"summary":{},"content":{"type":"text/x-c++src","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2985333278952154103"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1172975616400693679"},{"rel":"alternate","type":"text/x-c++src","href":"https://sites.google.com/a/chromium.org/dev/blink/unittesting/printto-confusing.cpp"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2985333278952154103"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2985333278952154103"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2985333278952154103"},{"rel":"edit-media","type":"text/x-c++src","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2985333278952154103"}],"author":[{"name":{"$t":"Tim Ansell"},"email":{"$t":"tansell@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/916002717183514750"},"published":{"$t":"2013-10-27T23:30:36.624Z"},"updated":{"$t":"2013-10-27T23:30:37.050Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-27T23:30:36.624Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Sun Oct 27 2013 16:30:36 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003ehartmanng\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-sun-oct-27-2013-16-30-36-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/916002717183514750"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/916002717183514750"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/916002717183514750"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-sun-oct-27-2013-16-30-36-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4022236323063704329"},"published":{"$t":"2013-10-27T17:51:35.662Z"},"updated":{"$t":"2013-10-27T17:51:35.702Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-27T17:51:35.662Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-10-27 at 10.50.40 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4022236323063704329"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4727746233434872159"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/perf-sheriffs/Screen%20Shot%202013-10-27%20at%2010.50.40%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4022236323063704329"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4022236323063704329"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4022236323063704329"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4022236323063704329"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3487139236734147214"},"published":{"$t":"2013-10-27T17:40:03.219Z"},"updated":{"$t":"2013-10-27T17:40:03.260Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-27T17:40:03.219Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-10-27 at 10.39.38 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3487139236734147214"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4727746233434872159"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/perf-sheriffs/Screen%20Shot%202013-10-27%20at%2010.39.38%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3487139236734147214"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3487139236734147214"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3487139236734147214"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3487139236734147214"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3177486413800373672"},"published":{"$t":"2013-10-27T17:34:13.623Z"},"updated":{"$t":"2013-10-27T17:34:13.660Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-27T17:34:13.623Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-10-27 at 10.33.54 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/3177486413800373672"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4727746233434872159"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/perf-sheriffs/Screen%20Shot%202013-10-27%20at%2010.33.54%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3177486413800373672"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3177486413800373672"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3177486413800373672"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/3177486413800373672"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2031973968004965629"},"published":{"$t":"2013-10-27T17:29:41.388Z"},"updated":{"$t":"2013-10-27T17:29:41.435Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-27T17:29:41.388Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-10-27 at 10.29.17 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/2031973968004965629"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4727746233434872159"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/perf-sheriffs/Screen%20Shot%202013-10-27%20at%2010.29.17%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2031973968004965629"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2031973968004965629"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2031973968004965629"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/2031973968004965629"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/4123779539901352759"},"published":{"$t":"2013-10-27T17:24:44.970Z"},"updated":{"$t":"2013-10-27T17:24:45.043Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-27T17:24:44.970Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"Screen Shot 2013-10-27 at 10.23.35 AM.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/4123779539901352759"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4727746233434872159"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/developers/tree-sheriffs/perf-sheriffs/Screen%20Shot%202013-10-27%20at%2010.23.35%20AM.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/4123779539901352759"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4123779539901352759"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/4123779539901352759"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/4123779539901352759"}],"author":[{}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5293961679556019134"},"published":{"$t":"2013-10-24T17:15:27.183Z"},"updated":{"$t":"2013-10-24T17:15:27.585Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-24T17:15:27.183Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 24 2013 10:15:27 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003ehartmanng\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-24-2013-10-15-27-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5293961679556019134"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5293961679556019134"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5293961679556019134"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-24-2013-10-15-27-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"XSl7JmA-\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3722372565311762602"},"published":{"$t":"2013-05-22T13:05:32.084Z"},"updated":{"$t":"2013-10-23T21:19:24.185Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-23T21:19:22.276Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Layered Components: Design"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Overview\" /\u003e\u003cbr /\u003eOverview\u003c/h2\u003e\u003cbr /\u003e\u003cfont size\u003d\"3\"\u003eChrome for iOS cannot use the content layer as-is due to the restrictions that Apple places on third-party browsers on iOS. Given this fact, the goal of this project is to enable iOS’s usage of chrome- and component-level features that:\u003cbr /\u003e\u003cul\u003e\u003cli\u003eMinimizes pain on Chromium developers, both for iOS and for other platforms\u003c/li\u003e\u003cli\u003eEnables Chromium developers developing multi-platform features to target iOS as well\u003c/li\u003e\u003c/ul\u003e\u003c/font\u003e\u003cspan style\u003d\"font-size:medium\"\u003eTo that end, we will be performing refactorings to introduce \u003cb\u003elayered components\u003c/b\u003e: components that consist of shared code that is content-free together with a driver based on the content layer and an alternative driver for iOS that uses an iOS-specific API.\u003c/span\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003c/font\u003e\u003cdiv\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Motivation\" /\u003eMotivation\u003c/h2\u003e\u003cbr /\u003e\u003cfont size\u003d\"3\"\u003eApple restricts third-party iOS apps to using UIWebView as the JavaScript/rendering engine and additionally to being single-process. This fact means that Chrome for iOS:\u003cbr /\u003e\u003cul\u003e\u003cli\u003eCannot use the existing content/ implementation, which is based on V8/Blink and is multiprocess.\u003c/li\u003e\u003cli\u003eCould provide at best a partial alternative implementation of the content API due to the black-box nature of UIWebView.\u003c/li\u003e\u003c/ul\u003e\u003c/font\u003e\u003cspan style\u003d\"font-size:medium\"\u003eAs a result, iOS usage of chrome- and component-level features currently requires a sea of ifdef’s, code modifications, and code additions. Upstreaming this surgery would introduce maintainability and readability challenges.\u003c/span\u003e\u003cfont size\u003d\"3\"\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/font\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003eThe fact that most Chromium developers have no visibility into iOS’s restrictions and requirements additionally causes a raised level of difficulty for developers looking to target feature work to iOS in addition to other platforms.\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Layered-Components\" /\u003eLayered Components\u003c/h2\u003e\u003cbr /\u003e\u003cfont size\u003d\"3\"\u003eOur approach to the challenges outlined above is to gradually \u003cb\u003eeliminate dependence on the content API in code that is used on iOS\u003c/b\u003e (see the below background for discussion of alternative approaches and how we converged on this approach).\u003cbr /\u003e\u003cbr /\u003eIn determining how to structure this approach within the codebase, we took the position that DEPS restrictions are easiest for developers to understand and introduce the least amount of maintainability pain when they are put within a recognizable structure. We will introduce \u003cb\u003elayered components\u003c/b\u003e. These components will live in one of a small number of known locations within the source tree (e.g., src/components). Each such component will consist of the following:\u003cbr /\u003e\u003cul\u003e\u003cli\u003eA core/ subdirectory consisting of code shared by all platforms. This code cannot depend on content/, and will contain e.g. core model logic of the component.\u003c/li\u003e\u003cli\u003eAn ios/ subdirectory that contains code that depends on an iOS-specific API and drives the shared code for iOS.\u003c/li\u003e\u003cli\u003eA content/ subdirectory that contains code that can depend on content/ and drives the shared code for all other platforms. For example, this subdirectory might contain a WebContentsObserver that invokes behavior of the shared code when a WebContents is destroyed.\u003c/li\u003e\u003c/ul\u003eThe technical details of our plan to realize this approach are detailed \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-technical-approach\"\u003ehere\u003c/a\u003e, and a detailed description of the proposed structure within the Chromium codebase is detailed \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/developers/design-documents/structure-of-layered-components-within-the-chromium-codebase\"\u003ehere\u003c/a\u003e.\u003c/font\u003e\u003cbr /\u003e\u003cbr /\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-FAQ\" /\u003eFAQ\u003c/h2\u003e\u003cfont size\u003d\"3\"\u003e\u003cul\u003e\u003cli\u003e\u003cb\u003eWon’t creating this structure introduce extra layering in the affected features?\u003c/b\u003e Inevitably it will. However, we have explicit goals of (a) minimizing added layering to reduce maintainability pain and (b) making decouplings as logical as possible (e.g., decoupling model code from code interacting with the renderer via IPC). We plan to work together with feature owners to develop agreeable designs.\u003c/li\u003e\u003cli\u003e\u003cb\u003eWhat is this “iOS-specific API”?\u003c/b\u003e It will be an API that will have a similar purpose as the content API (e.g., allow an object to know when a webpage has finished loading) but will be much smaller. In a sense, it will be a “content API around UIWebView.”\u003c/li\u003e\u003cli\u003e\u003cb\u003eWill there be a wrapper API around the content API and the iOS API?\u003c/b\u003e Unknown at this time. The goal is to avoid such an API; however, if it turns out that having a thin wrapper API would greatly simplify the structure of multiple components, such an API might be introduced.\u003c/li\u003e\u003cli\u003e\u003cb\u003eWithout a wrapper API, how will you possibly handle WebContents/NavigationController/BrowserContext/etc.?\u003c/b\u003e These questions will have to be examined on a case-by-case basis. Starting from the position that we would like to avoid a wrapper API will enable isolating the cases (if any) where the lack of such a wrapper API causes significant pain.\u003c/li\u003e\u003cli\u003e\u003cb\u003eWhat if the shared code of a layered component needs to talk to its driver?\u003c/b\u003e We expect that in general communication between the shared code of a layered component and its driver will be bi-directional. Communication from the shared code to a driver will be done via classes that the shared code declares and drivers define (the exact fashion in which this will be done will likely have to be approached on a case-by-case basis with the goal of minimizing boilerplate/code duplication).\u003c/li\u003e\u003cli\u003e\u003cb\u003eWill this work make the Chromium codebase less maintainable as a whole?\u003c/b\u003e While the primary motivation of this project is to enable upstream code/features to be shared by (and developed for) iOS in the most maintainable way, we see several other potential benefits that are independent of iOS:\u003c/li\u003e\u003cul\u003e\u003cli\u003eMitigate the monolithic nature of chrome/browser\u003c/li\u003e\u003cli\u003eEnable simpler unit testing of the code that will be shared\u003c/li\u003e\u003cli\u003ePerform refactorings that increase understandability of the impacted features\u003c/li\u003e\u003c/ul\u003e\u003cli\u003e\u003cb\u003eHow large is the scope of this project?\u003c/b\u003e Of the ~80 directories under chrome/browser, iOS uses ~30.\u003c/li\u003e\u003cli\u003e\u003cb\u003eI think that approach \u0026lt;X\u0026gt; would be better!\u003c/b\u003e We welcome feedback and discussion; please read the background section below as context.\u003c/li\u003e\u003c/ul\u003e\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Background:-iOS-and-the-Content-API\" /\u003eBackground: iOS and the Content API\u003c/h2\u003e\u003cbr /\u003e\u003cfont size\u003d\"3\"\u003eWe have examined several approaches to iOS’s usage of content:\u003cbr /\u003e\u003col\u003e\u003cli\u003eiOS uses all the parts of the content API that it needs/can support, providing alternative partial implementations of interfaces for which it cannot share the existing full-fledged implementation (e.g., WebContents).\u003c/li\u003e\u003cli\u003eiOS uses only the parts of the content API for which it can share the implementations, refactoring the Chromium codebase to remove and disallow usage of problematic parts of the content API (e.g., WebContents) in shared code.\u003c/li\u003e\u003cli\u003eiOS does not use the content API (the approach that we ultimately decided on).\u003c/li\u003e\u003c/ol\u003eThe conclusion re: Approach 1 was that the fact that iOS would only be able to provide a partial implementation of the content API would make it more challenging for developers to develop against the API: they would have to always be aware of (a) whether the given piece of code that they were working on was shared on iOS, and (b) which subsets of the content API were OK to use in code shared on iOS.\u003cbr /\u003e\u003cbr /\u003eThe conclusion re: approach 2 was similar to that re: approach 1, with the added concern that performing somewhat arbitrary-looking refactorings throughout the codebase would introduce maintainability and readability problems (initial CLs targeting this approach bore out these fears).\u003c/font\u003e\u003ch2\u003e\u003ca name\u003d\"TOC-Contact\" /\u003eContact\u003c/h2\u003e\u003c/div\u003e\u003cdiv\u003e\u003cfont size\u003d\"3\"\u003eStuart Morgan (stuartmorgan@) and Colin Blundell (blundell@) are the leads on this project. Darin Fisher (darin@) and John Abd-El-Malek (jam@) are providing guidance, direction and approval.\u003c/font\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3863791766242792620"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3722372565311762602"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3722372565311762602"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3722372565311762602"}],"author":[{"name":{"$t":"Colin Blundell"},"email":{"$t":"blundell@chromium.org"}}],"sites$pageName":{"$t":"layered-components-design"},"sites$revision":{"$t":"24"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/746301194887530595"},"published":{"$t":"2013-10-23T21:06:11.923Z"},"updated":{"$t":"2013-10-23T21:06:12.260Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-23T21:06:11.923Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Wed Oct 23 2013 14:06:11 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003ehartmanng\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-wed-oct-23-2013-14-06-11-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/746301194887530595"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/746301194887530595"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/746301194887530595"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-wed-oct-23-2013-14-06-11-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8022664490162689444"},"published":{"$t":"2013-10-23T20:06:59.175Z"},"updated":{"$t":"2013-10-23T20:07:00.984Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-23T20:06:59.175Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Wed Oct 23 2013 13:06:58 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003ehartmanng\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-wed-oct-23-2013-13-06-58-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8022664490162689444"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8022664490162689444"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8022664490162689444"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-wed-oct-23-2013-13-06-58-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7156375137617031226"},"published":{"$t":"2013-10-22T22:44:23.066Z"},"updated":{"$t":"2013-10-22T22:44:23.478Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-22T22:44:23.066Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 22 2013 15:44:22 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-22-2013-15-44-22-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7156375137617031226"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7156375137617031226"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7156375137617031226"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-22-2013-15-44-22-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/670635892829727965"},"published":{"$t":"2013-10-22T22:31:43.553Z"},"updated":{"$t":"2013-10-22T22:31:43.899Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-22T22:31:43.553Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 22 2013 15:31:43 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-22-2013-15-31-43-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/670635892829727965"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/670635892829727965"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/670635892829727965"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-22-2013-15-31-43-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5253153127574736362"},"published":{"$t":"2013-10-22T19:39:53.774Z"},"updated":{"$t":"2013-10-22T19:39:54.140Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-22T19:39:53.774Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 22 2013 12:39:53 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-22-2013-12-39-53-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5253153127574736362"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5253153127574736362"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5253153127574736362"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-22-2013-12-39-53-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5593750754013515319"},"published":{"$t":"2013-10-22T15:07:44.586Z"},"updated":{"$t":"2013-10-22T15:07:44.991Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-22T15:07:44.586Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 22 2013 08:07:44 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-22-2013-08-07-44-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5593750754013515319"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5593750754013515319"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5593750754013515319"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-22-2013-08-07-44-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2822388133442645790"},"published":{"$t":"2013-10-19T00:25:20.329Z"},"updated":{"$t":"2013-10-19T00:25:20.671Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-19T00:25:20.329Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Fri Oct 18 2013 17:25:20 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-fri-oct-18-2013-17-25-20-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2822388133442645790"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2822388133442645790"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2822388133442645790"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-fri-oct-18-2013-17-25-20-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5776061334679495577"},"published":{"$t":"2013-10-17T19:32:46.259Z"},"updated":{"$t":"2013-10-17T19:32:46.654Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-17T19:32:46.259Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 17 2013 12:32:46 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-17-2013-12-32-46-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5776061334679495577"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5776061334679495577"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5776061334679495577"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-17-2013-12-32-46-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3398843520640783638"},"published":{"$t":"2013-10-17T18:21:06.248Z"},"updated":{"$t":"2013-10-17T18:21:06.809Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-17T18:21:06.248Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 17 2013 11:21:06 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-17-2013-11-21-06-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3398843520640783638"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3398843520640783638"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3398843520640783638"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-17-2013-11-21-06-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7502657987108443836"},"published":{"$t":"2013-10-17T18:18:35.684Z"},"updated":{"$t":"2013-10-17T18:18:35.961Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-17T18:18:35.684Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 17 2013 11:18:35 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-17-2013-11-18-35-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7502657987108443836"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7502657987108443836"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7502657987108443836"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-17-2013-11-18-35-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/47959543052466475"},"published":{"$t":"2013-10-17T15:02:27.081Z"},"updated":{"$t":"2013-10-17T15:02:27.429Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-17T15:02:27.081Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 17 2013 08:02:26 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-17-2013-08-02-26-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/47959543052466475"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/47959543052466475"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/47959543052466475"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-17-2013-08-02-26-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7571086363964177093"},"published":{"$t":"2013-10-17T07:17:03.646Z"},"updated":{"$t":"2013-10-17T07:17:04.743Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-17T07:17:03.646Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 17 2013 00:17:03 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-17-2013-00-17-03-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7571086363964177093"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7571086363964177093"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7571086363964177093"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-17-2013-00-17-03-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/397094306518099348"},"published":{"$t":"2013-10-17T06:20:07.605Z"},"updated":{"$t":"2013-10-17T06:20:07.648Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-17T06:20:07.605Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"c720-chromebook-annotated-innards.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/397094306518099348"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9041942356411587249"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook/c720-chromebook-annotated-innards.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/397094306518099348"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/397094306518099348"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/397094306518099348"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/397094306518099348"}],"author":[{"name":{"$t":"David Parker"},"email":{"$t":"dparker@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1671008301243558776"},"published":{"$t":"2013-10-16T20:15:03.986Z"},"updated":{"$t":"2013-10-16T20:15:04.292Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-16T20:15:03.986Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Wed Oct 16 2013 13:15:03 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-wed-oct-16-2013-13-15-03-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1671008301243558776"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1671008301243558776"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1671008301243558776"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-wed-oct-16-2013-13-15-03-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5136976252884837385"},"published":{"$t":"2013-10-16T19:59:55.514Z"},"updated":{"$t":"2013-10-16T19:59:55.921Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-16T19:59:55.514Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Wed Oct 16 2013 12:59:55 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-wed-oct-16-2013-12-59-55-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5136976252884837385"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5136976252884837385"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5136976252884837385"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-wed-oct-16-2013-12-59-55-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2095215298271259248"},"published":{"$t":"2013-10-15T23:06:34.069Z"},"updated":{"$t":"2013-10-15T23:06:34.309Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-15T23:06:34.069Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 15 2013 16:06:33 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-15-2013-16-06-33-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2095215298271259248"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2095215298271259248"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2095215298271259248"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-15-2013-16-06-33-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"USl7JmA9\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8455202019639247095"},"published":{"$t":"2013-08-26T19:39:32.241Z"},"updated":{"$t":"2013-10-14T22:39:23.011Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T22:39:21.142Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#webpage","label":"webpage"}],"title":{"$t":"Layout Test Contest"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003e\u003cdiv dir\u003d\"ltr\"\u003e\u003ch2 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Why-Fix-all-test-ordering-issues-so-we-can-enable---order-random-seeded-by-default.-Drive-number-of-lines-in-test_expectations-to-0-so-it-is-easier-to-maintain.-Win-fame-and-prizes-\" /\u003e\u003cspan style\u003d\"background-color:transparent\"\u003e\u003cfont size\u003d\"3\"\u003eWhy?\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt;font-weight:normal\"\u003e Fix all test ordering issues so we can enable --order\u003drandom-seeded by default. \u003c/span\u003e\u003cspan style\u003d\"background-color:transparent;font-weight:normal;font-size:13px\"\u003e Drive number of lines in test_expectations to 0 so it is easier to maintain.  Win fame and prizes!\u003c/span\u003e\u003c/h2\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Who-Everyone-Yes-you-can-participate-even-if-you-ve-never-contributed-to-Blink-before-In-fact-this-is-the-perfect-way-to-get-some-Blink-commits-under-your-belt-You-don-t-need-to-be-a-Google-employee-either.\" /\u003eWho? \u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003eEveryone!  Yes, you can participate even if you've never contributed to Blink before!  In fact, this is the perfect way to get some Blink commits under your belt! You don't need to be a Google employee either.\u003c/span\u003e\u003c/h3\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Dates:-The-contest-will-begin-on-9-30-and-end-on-10-20-at-11:59pm-PST-extended-to-10-27-at-11:59pm-PST-All-code-must-be-submitted-for-review-during-these-dates-to-be-eligible.\" /\u003eDates: \u003cspan style\u003d\"font-size:13px\"\u003e\u003cspan style\u003d\"font-weight:normal\"\u003eThe contest will begin on 9/30 \u003c/span\u003e\u003cstrike style\u003d\"font-weight:normal\"\u003eand end on 10/20 at 11:59pm PST \u003c/strike\u003e\u003cfont color\u003d\"#ff0000\"\u003e extended to \u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:13px;background-color:transparent\"\u003e\u003cfont color\u003d\"#ff0000\"\u003e10/27 at 11:59pm PST!!!\u003c/font\u003e\u003c/span\u003e\u003cspan style\u003d\"font-size:13px;font-weight:normal;background-color:transparent\"\u003e  All code must be submitted for review during these dates to be eligible.\u003c/span\u003e\u003c/h3\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Scoring:-Points-will-be-awarded-based-on-the-tasks-completed.-Point-values-for-each-task-are-explained-below.-Each-participant-s-score-will-be-the-sum-of-his-or-her-points.-See-the-leaderboard-\" /\u003eScoring: \u003cspan style\u003d\"font-weight:normal;font-size:13px\"\u003ePoints will be awarded based on the tasks completed. Point values for each task are explained below. Each participant's score will be the sum of his or her points.  See the \u003ca href\u003d\"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard\"\u003eleaderboard\u003c/a\u003e!\u003c/span\u003e\u003c/h3\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Winners-Prizes:\" /\u003eWinners \u0026amp; Prizes:\u003c/h3\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003eThere are many chances to win!  In addition to standard 1st, 2nd, 3rd Place, there are additional prizes:\u003c/div\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli style\u003d\"font-family:trebuchet ms\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eCheetah: First person to 250 points. Start off the contest with a bang!\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"font-family:trebuchet ms\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eTop Reviewer: Awarded to the participant with the highest number of points from code reviews only.  Show off your code review skillz!\u003c/span\u003e\u003c/li\u003e\r\n\u003cli style\u003d\"font-family:trebuchet ms\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eBest Yak Shave: Awarded to the participant with the most ridiculous patch, or series of patches, required to solve a \"simple\" problem.  Show your perseverance!\u003c/span\u003e\u003c/li\u003e\u003cli\u003e\u003cfont face\u003d\"trebuchet ms\"\u003eTop Slacker: Awarded to the participant with the highest number of points gained, who starts AFTER October 14, 11:59pm PST.\u003c/font\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003eWinners will select a prize from a prize category.  \u003cspan style\u003d\"font-size:10pt\"\u003eAny prize can be exchanged for a \u003c/span\u003e\u003cb style\u003d\"font-size:10pt\"\u003e\"Get out of gardening free pass!\" - Priceless!\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\u003cb style\u003d\"font-size:10pt\"\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;border:1px dashed black;padding:3px;margin:5px\"\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-1st-Prize:-Awarded-to-the-participant-with-the-highest-number-of-points.\" /\u003e1st Prize: Awarded to the participant with the highest number of points.\u003c/h4\u003e\r\n\u003cdiv\u003e\u003cb\u003eYour choice of: \u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv\u003e\u003cbr /\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;text-align:center\"\u003eIndoor Sky Diving Party\u003cbr /\u003e\r\nfor 12\u003cbr /\u003e\r\n\u003cimg alt\u003d\"Vegas Indoor Skydiving Elvis\" height\u003d\"133\" src\u003d\"http://media-cdn.tripadvisor.com/media/photo-s/01/ca/ea/7a/vegas-indoor-skydiving.jpg\" style\u003d\"border:0px;vertical-align:text-top;display:block;margin:0px auto;color:rgb(44,44,44);font-family:Arial,Tahoma,Bitstream Vera Sans,sans-serif;font-size:12px;background-color:rgb(243,243,243)\" width\u003d\"200\" /\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;text-align:center\"\u003e\u003ca href\u003d\"http://www.kitchit.com/listings/late-summer-farmers-market-dinner\" style\u003d\"color:rgb(85,26,139)\" rel\u003d\"nofollow\"\u003eKitchit Dinner Party\u003c/a\u003e \u003cbr /\u003e\r\nfor 8\u003cbr /\u003e\r\n\u003cdiv\u003e\u003ca href\u003d\"https://kitchit-static01.insnw.net/images/4453/Large/6215_1160623569817_1054627764_484055_6067109_n.jpg\" imageanchor\u003d\"1\" style\u003d\"color:rgb(85,26,139)\" rel\u003d\"nofollow\"\u003e\u003cimg border\u003d\"0\" height\u003d\"133\" src\u003d\"https://kitchit-static01.insnw.net/images/4453/Large/6215_1160623569817_1054627764_484055_6067109_n.jpg\" width\u003d\"200\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;text-align:center\"\u003eSennheiser HD 650 Headphones\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"200\" rel\u003d\"http://ecx.images-amazon.com/images/I/81zggHtrqML._SL1500_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/81zggHtrqML._SY300_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"142\" /\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;text-align:center\"\u003eiRobot Roomba or Scooba\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"140\" rel\u003d\"http://ecx.images-amazon.com/images/I/51ke4PvOGqL._SL1094_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/41kXrlCafUL._SX450_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"200\" /\u003e\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;text-align:center\"\u003eLG Electronics 50LN5400 50-Inch 1080p 120Hz LED-LCD HDTV with Smart Share\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"175\" rel\u003d\"http://ecx.images-amazon.com/images/I/81M29eUuQgL._SL1500_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/81M29eUuQgL._SX300_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"200\" /\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;text-align:center\"\u003e1982 Port Ellen 30yr Scotch\u003cbr /\u003e\r\n\u003ca style\u003d\"color:rgb(145,140,52);display:block;margin:0px 0px 1em;font-family:Arial,Helvetica,sans-serif;font-size:12px;background-color:rgb(255,255,254)\"\u003e\u003cimg alt\u003d\"1982 Port Ellen 30 Year Old \u0026quot;K\u0026amp;L Exclusive\u0026quot; Sovereign Single Barrel Cask Strength Single Malt Whisky 750ml\" height\u003d\"200\" src\u003d\"http://www.klwines.com/images/skus/1117203l.jpg\" style\u003d\"vertical-align:middle\" width\u003d\"83\" /\u003e\u003c/a\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"clear:both\" /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;border:1px dashed black;padding:3px;margin:5px\"\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-2nd-Prize:-Awarded-to-the-participant-with-the-second-highest-number-of-points.\" /\u003e2nd Prize: Awarded to the participant with the second highest number of points.\u003c/h4\u003e\r\n\u003cdiv\u003e\u003cb\u003eYour choice of:\u003c/b\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eIndoor Sky Diving Party\u003cbr /\u003e\r\nfor 5\u003cbr /\u003e\r\n\u003cimg alt\u003d\"Vegas Indoor Skydiving Elvis\" height\u003d\"133\" src\u003d\"http://media-cdn.tripadvisor.com/media/photo-s/01/ca/ea/7a/vegas-indoor-skydiving.jpg\" style\u003d\"border:0px;vertical-align:text-top;display:block;margin:0px auto;color:rgb(44,44,44);font-family:Arial,Tahoma,Bitstream Vera Sans,sans-serif;font-size:12px;background-color:rgb(243,243,243)\" width\u003d\"200\" /\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003e\u003ca href\u003d\"http://www.kitchit.com/listings/late-summer-farmers-market-dinner\" style\u003d\"color:rgb(85,26,139)\" rel\u003d\"nofollow\"\u003eKitchit Dinner Party\u003c/a\u003e \u003cbr /\u003e\r\nfor 4\u003cbr /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"133\" src\u003d\"https://kitchit-static01.insnw.net/images/4453/Large/6215_1160623569817_1054627764_484055_6067109_n.jpg\" style\u003d\"border:0px;padding:0px;color:rgb(85,26,139);text-align:left\" width\u003d\"200\" /\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eNexus 7 32G\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"200\" rel\u003d\"http://ecx.images-amazon.com/images/I/71vsIgVGu9L._SL1500_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/71mCTJlJwGL._SY679_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"140\" /\u003e\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eSonos Play 3\u003cbr /\u003e\r\n\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"185\" rel\u003d\"http://ecx.images-amazon.com/images/I/81VEXB6fJwL._SL1402_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/81VEXB6fJwL._SX522_.jpg\" style\u003d\"font-size:small;display:inline;font-family:verdana,arial,helvetica,sans-serif\" width\u003d\"200\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eBreville Smart Oven Convection Toaster Oven with Element IQ\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"120\" rel\u003d\"http://ecx.images-amazon.com/images/I/81v4dO2kn3L._SL1500_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/41W8PMvH9FL._SX450_.jpg\" style\u003d\"font-size:small;display:inline;font-family:verdana,arial,helvetica,sans-serif\" width\u003d\"200\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003e1996 Opus One Napa Valley Proprietary Red\u003cbr /\u003e\r\n\u003ca style\u003d\"color:rgb(145,140,52);display:block;margin:0px 0px 1em;font-family:Arial,Helvetica,sans-serif;font-size:12px;background-color:rgb(255,255,254)\"\u003e\u003cimg alt\u003d\"1996 Opus One Napa Valley Proprietary Red\" height\u003d\"200\" src\u003d\"http://www.klwines.com/images/skus/301229l.jpg\" style\u003d\"vertical-align:middle\" width\u003d\"83\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"clear:both\" /\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"border:1px dashed black;padding:3px;margin:5px\"\u003e\r\n\u003ch4 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-3rd-Prize:-Awarded-to-the-participant-with-the-third-highest-number-of-points.\" /\u003e3rd Prize: Awarded to the participant with the third highest number of points.\u003c/h4\u003e\r\n\u003ch4 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Cheetah:-First-person-to-250-points.-Start-off-the-contest-with-a-bang-\" /\u003eCheetah: First person to 250 points. Start off the contest with a bang!\u003c/h4\u003e\r\n\u003ch4 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Top-Reviewer:-Awarded-to-the-participant-with-the-highest-number-of-points-from-code-reviews-only.-Show-off-your-code-review-skillz-\" /\u003eTop Reviewer: Awarded to the participant with the highest number of points from code reviews only.  Show off your code review skillz!\u003c/h4\u003e\u003cdiv\u003e\u003cb\u003e\u003cfont face\u003d\"trebuchet ms\"\u003eTop Slacker: Awarded to the participant with the highest number of points gained, who starts AFTER October 14, 11:59pm PST.\u003c/font\u003e\u003c/b\u003e\u003c/div\u003e\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\u003cbr /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\u003cb\u003eYour choice of:\u003c/b\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\u003cb\u003e\u003cbr /\u003e\r\n\u003c/b\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003e\u003ca href\u003d\"http://www.google.com/url?q\u003dhttp%3A%2F%2Fwww.kitchit.com%2Flistings%2Flate-summer-farmers-market-dinner\u0026amp;sa\u003dD\u0026amp;sntz\u003d1\u0026amp;usg\u003dAFrqEzeeon2ePMRBRFaHc6luP02HSn0e3w\" style\u003d\"color:rgb(85,26,139)\"\u003eKitchit Dinner Party\u003c/a\u003e \u003cbr /\u003e\r\nfor 2\u003cbr /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"133\" src\u003d\"https://kitchit-static01.insnw.net/images/4453/Large/6215_1160623569817_1054627764_484055_6067109_n.jpg\" style\u003d\"font-size:10pt;border:0px;padding:0px;color:rgb(85,26,139);text-align:left\" width\u003d\"200\" /\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eSodaStream Pure w/ Soda Starter Kit\u003cbr /\u003e\r\n\u003ctable\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd style\u003d\"margin:0px\"\u003e\u003cimg alt\u003d\"Pure - Soda Starter Kit \" border\u003d\"0\" height\u003d\"200\" src\u003d\"http://www.sodastreamusa.com/Assets/ProductImages/pure_soda_starter_black.jpg\" width\u003d\"200\" /\u003e\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;float:left;height:250px;width:313px;text-align:center\"\u003eSennheiser HD 558 Headphones\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"200\" rel\u003d\"\" src\u003d\"http://ecx.images-amazon.com/images/I/41ljcZIdgGL._SY300_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"153\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;float:left;height:250px;width:313px;text-align:center\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eKindle Paperwhite, 3G\u003c/span\u003e\u003cbr /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"http://g-ecx.images-amazon.com/images/G/01/kindle/dp/2012/KC/technical._V376689304_.jpg\" style\u003d\"margin-left:30px\" width\u003d\"189\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;float:left;height:250px;width:313px;text-align:center\"\u003eBreville Compact Smart Oven Toaster Oven with Element IQ\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"128\" rel\u003d\"http://ecx.images-amazon.com/images/I/812jFVXtbIL._SL1500_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/41AU85%2BnMFL._SX450_.jpg\" style\u003d\"font-size:small;display:inline;font-family:verdana,arial,helvetica,sans-serif\" width\u003d\"200\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;float:left;height:250px;width:313px;text-align:center\"\u003eMacallan 18 year old Single Malt \u003cbr /\u003e\r\n\u003ca style\u003d\"color:rgb(145,140,52);display:block;margin:0px 0px 1em;font-family:Arial,Helvetica,sans-serif;font-size:12px;background-color:rgb(255,255,254)\"\u003e\u003cimg alt\u003d\"Macallan 18 year old Single Malt Whisky 750ml\" height\u003d\"200\" src\u003d\"http://www.klwines.com/images/skus/620010l.jpg\" style\u003d\"vertical-align:middle\" width\u003d\"83\" /\u003e\u003c/a\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;clear:both\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms;border:1px dashed black;padding:3px;margin:5px\"\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Best-Yak-Shave:-Awarded-to-the-participant-with-the-most-ridiculous-patch-or-series-of-patches-required-to-solve-a-simple-problem.\" /\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eBest \u003c/span\u003e\u003ca href\u003d\"http://en.wiktionary.org/wiki/yak_shaving\" style\u003d\"color:rgb(85,26,139);background-color:transparent;font-size:10pt\" rel\u003d\"nofollow\"\u003eYak Shave\u003c/a\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e: Awarded to the participant with the most ridiculous patch, or series of patches, required to solve a \"simple\" problem.\u003c/span\u003e\u003c/h4\u003e\r\n\u003cdiv style\u003d\"text-align:center\"\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003e\u003cb\u003eYour very own Shaving Yak Action Figure!\u003c/b\u003e\u003c/span\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"text-align:center;font-size:130pt\"\u003e\u003cimg alt\u003d\"\" height\u003d\"200\" rel\u003d\"\" src\u003d\"http://ecx.images-amazon.com/images/I/41K5N9X899L._SX385_.jpg\" style\u003d\"display:inline\" width\u003d\"180\" /\u003e +\u003c/div\u003e\r\n\u003cdiv /\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Your-choice-of:-\" /\u003e\u003cb style\u003d\"background-color:transparent;font-size:10pt\"\u003eYour choice of: \u003c/b\u003e\u003c/h4\u003e\r\n\u003cdiv\u003e\u003cb\u003e\u003cspan style\u003d\"font-weight:normal\"\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eIndoor Sky Diving\u003cbr /\u003e\r\nfor 2\u003cbr /\u003e\r\n\u003cimg alt\u003d\"Vegas Indoor Skydiving Elvis\" height\u003d\"133\" src\u003d\"http://media-cdn.tripadvisor.com/media/photo-s/01/ca/ea/7a/vegas-indoor-skydiving.jpg\" style\u003d\"border:0px;vertical-align:text-top;display:block;margin:0px auto;color:rgb(44,44,44);font-family:Arial,Tahoma,Bitstream Vera Sans,sans-serif;font-size:12px;background-color:rgb(243,243,243)\" width\u003d\"200\" /\u003e\r\n\u003cdiv /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eSodaStream Genesis w/ Soda Starter Kit\u003cbr /\u003e\r\n\u003ctable style\u003d\"margin-bottom:8px;color:rgb(51,51,51);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;line-height:16px\"\u003e\r\n\u003ctbody\u003e\r\n\u003ctr\u003e\r\n\u003ctd\u003e\r\n\u003cdiv style\u003d\"float:left;width:313px;height:250px;margin:0px\"\u003e\u003cimg alt\u003d\"Genesis - Soda Starter Kit \" border\u003d\"0\" height\u003d\"200\" src\u003d\"http://www.sodastreamusa.com/Assets/ProductImages/genesis_soda_starter_black.jpg\" width\u003d\"200\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/td\u003e\r\n\u003c/tr\u003e\r\n\u003c/tbody\u003e\r\n\u003c/table\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eSennheiser HD-280 PRO Headphones\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"200\" rel\u003d\"\" src\u003d\"http://ecx.images-amazon.com/images/I/413dm8SG1nL._SY300_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"153\" /\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eKindle Paperwhite, Wi-Fi\u003cbr /\u003e\r\n\u003cimg border\u003d\"0\" height\u003d\"200\" src\u003d\"http://g-ecx.images-amazon.com/images/G/01/kindle/dp/2012/KC/technical._V376689304_.jpg\" style\u003d\"margin-right:30px\" width\u003d\"189\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003eAeroGarden Classic 7-Pod with Gourmet Herb Seed Kit\u003cbr /\u003e\r\n\u003cimg alt\u003d\"\" height\u003d\"200\" rel\u003d\"http://ecx.images-amazon.com/images/I/91SWEsahw1L._SL1500_.jpg\" src\u003d\"http://ecx.images-amazon.com/images/I/51nhCytPscL._SY450_.jpg\" style\u003d\"display:inline;font-family:verdana,arial,helvetica,sans-serif;font-size:small\" width\u003d\"184\" /\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"float:left;height:250px;width:313px;text-align:center\"\u003e2003 Dom Perignon\u003cbr /\u003e\r\n\u003ca style\u003d\"color:rgb(32,67,66);display:block;margin:0px 0px 1em;font-family:Arial,Helvetica,sans-serif;font-size:12px;background-color:rgb(255,255,254)\"\u003e\u003cimg alt\u003d\"2003 Moet \u0026amp; Chandon \u0026quot;Dom Pérignon\u0026quot; Brut Champagne\" height\u003d\"200\" src\u003d\"http://www.klwines.com/images/skus/1089853l.jpg\" style\u003d\"vertical-align:middle\" width\u003d\"83\" /\u003e\u003c/a\u003e\r\n\u003cdiv style\u003d\"margin-right:auto;margin-left:auto\" /\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"clear:both\" /\u003e\r\n\u003c/span\u003e\u003c/b\u003e\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003ch4 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-For-non-MTV-based-winners-suitable-equivalent-prizes-will-be-awarded-if-necessary.\" /\u003e*For non-MTV based winners, suitable equivalent prizes will be awarded if necessary.\u003c/h4\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"howto\" style\u003d\"color:black\"\u003eHow to Participate\u003c/a\u003e\u003c/h3\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\r\n\u003col\u003e\u003cli\u003eComplete any of the tasks below.\u003c/li\u003e\r\n\u003cli\u003eFor each task, submit your participation info using \u003ca href\u003d\"https://docs.google.com/a/chromium.org/forms/d/1MHJ_WC-niQkhvnyofWkEl-zaRUZpz7fxrLkllDKR-p8/viewform\"\u003ethis form\u003c/a\u003e.  \u003cfont color\u003d\"#FF0000\"\u003eSorry, any task completed, but not submitted in this manner, will not be eligible.\u003c/font\u003e\u003c/li\u003e\r\n\u003cli\u003eProfit!\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/div\u003e\r\n\u003ch2 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-Points\" /\u003ePoints\u003c/h2\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003ePoints are not additive. Each patch can only apply to one category.\u003c/div\u003e\r\n\u003ch4 style\u003d\"font-family:trebuchet ms\"\u003e\u003ca name\u003d\"TOC-C-or-Python-change-fix-to-endemic-test-flakiness\" /\u003eC++ or Python change fix to endemic test flakiness\u003c/h4\u003e\r\n\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003ePoints: 50\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eExamples: reset some state between test runs or fix a race condition in run-webkit-tests.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Fix-a-line-or-flaky-test-in-TestExpectations-that-crashes\" /\u003e\u003cfont face\u003d\"trebuchet ms\"\u003eFix a line or flaky test in TestExpectations that crashes\u003c/font\u003e\u003c/h4\u003e\r\n\u003cdiv style\u003d\"color:rgb(34,34,34);font-family:arial,sans-serif\"\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003ePoints: 5/line\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"background-color:transparent\"\u003eIncludes [ Pass Crash ] lines.\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003cdiv\u003e\u003cfont color\u003d\"#222222\" face\u003d\"arial, sans-serif\"\u003e\u003cb\u003eFix a line or flaky test in TestExpectations that doesn't crash\u003c/b\u003e\u003c/font\u003e\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\r\n\u003cul\u003e\u003cli\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003ePoints: 3/line\u003c/span\u003e\u003c/li\u003e\u003c/ul\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Remove-a-line-from-TestExpectations-with-no-other-changes-whitespace-and-comment-lines-do-not-count-\" /\u003e Remove a line from TestExpectations (with no other changes, whitespace and comment lines do *not* count)\u003c/h4\u003e\r\n\u003cdiv\u003e\r\n\u003cul\u003e\u003cli\u003ePoints: 1/line\u003c/li\u003e\r\n\u003cli\u003eThis is for TestExpectations-only changes. If you made a non-TestExpectations-only change that fixed more tests than you realized, you can still submit a TestExpectations-only change for 3 points per line.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003ch4\u003e\u003ca name\u003d\"TOC-Code-review-a-C-Python-change\" /\u003e\u003cspan style\u003d\"background-color:transparent;font-size:10pt\"\u003eCode review a C++/Python change\u003c/span\u003e\u003c/h4\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\r\n\u003cul\u003e\u003cli\u003ePoints: 3\u003c/li\u003e\r\n\u003cli\u003eAgain, pure TestExpectations-only changes don't count.\u003c/li\u003e\r\n\u003cli\u003eIt's the reviewer's responsibility to fill out the form above.\u003c/li\u003e\u003c/ul\u003e\r\n\u003c/div\u003e\r\n\u003ch2 style\u003d\"font-family:trebuchet ms\"\u003eHow To\u003ca name\u003d\"howto\"\u003e \u003c/a\u003e\u003c/h2\u003e\r\n\u003cdiv style\u003d\"font-family:trebuchet ms\"\u003e\r\n\u003cdiv style\u003d\"font-family:Arial,Verdana,sans-serif\"\u003e\r\n\u003cp\u003eHere are some ideas for ways to identify test flakiness/ordering issues.\u003c/p\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-1.-Fix-filed-test-ordering-bugs-good-way-to-find-C-endemic-flakiness-issues-\" /\u003e1. Fix filed test ordering bugs (good way to find C++ endemic flakiness issues!!)\u003c/h3\u003e\u003cp\u003e\u003ca href\u003d\"https://code.google.com/p/chromium/issues/list?q\u003dlabel:LayoutTestOrdering\"\u003ehttps://code.google.com/p/chromium/issues/list?q\u003dlabel:LayoutTestOrdering\u003c/a\u003e\u003c/p\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms!important\"\u003e\u003ca name\u003d\"TOC-2.-Run-tests-in-a-random-order-and-diagnose-failures\" /\u003e2. Run tests in a random order and diagnose failures\u003c/h3\u003e\r\n\u003cdiv\u003e\r\n\u003col\u003e\u003cli\u003eRun \"run-webkit-tests --order\u003drandom --no-retry\".\u003c/li\u003e\r\n\u003cli\u003eRun \"./Tools/Scripts/print-test-ordering\" and save the output to a file. This outputs the tests run in the order they were run on each content_shell instance.\u003c/li\u003e\r\n\u003cli\u003eFor each test that fails:\u003c/li\u003e\r\n\u003col\u003e\u003cli\u003eFind which worker it ran on.\u003c/li\u003e\r\n\u003cli\u003eCreate a file that contains only the tests run on that worker in the same order as in your saved output file.\u003c/li\u003e\r\n\u003cli\u003erun-webkit-tests --child-processes\u003d1 --order\u003dnone --test-list\u003dpath/to/file/from/previous/step\u003c/li\u003e\r\n\u003cli\u003eIf the test doesn't fail here, then the test itself is probably just flaky. If it does, remove some lines from the file created in step 2.2 and repeat step 3. Continue repeating until you've found the dependency. If the test fails when run by itself, but passes on the bots, that means that it depends on another test to pass. In this case, you need to generate the list of tests run by \"run-webkit-tests --order\u003dnatural\" and repeat this process to find which test causes the test in question to *pass* (e.g. \u003ca href\u003d\"http://crbug.com/262793\"\u003ecrbug.com/262793\u003c/a\u003e).\u003c/li\u003e\r\n\u003cli\u003eFile a bug and give it the LayoutTestOrdering label, e.g. \u003ca href\u003d\"http://crbug.com/262787\"\u003ecrbug.com/262787\u003c/a\u003e or \u003ca href\u003d\"http://crbug.com/262791\"\u003ecrbug.com/262791\u003c/a\u003e\u003c/li\u003e\r\n\u003c/ol\u003e\r\n\u003c/ol\u003e\r\n\u003ch3 style\u003d\"font-family:trebuchet ms!important\"\u003e\u003ca name\u003d\"TOC-Run-tests-in-isolation\" /\u003e3. Run tests in isolation\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cdiv style\u003d\"font-family:Arial,Verdana,sans-serif\"\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eRun \"run-webkit-tests --batch-size 1 --no-retry\". This starts up a new content_shell instance for each test. Tests that fail when run in isolation but pass when run as part of the full test suite represent some state that we're not properly resetting between test runs or some state that we're not properly setting when starting up content_shell. You might want to run with --time-out-ms\u003d60000 to weed out tests that timeout due to waiting on content_shell startup time.\u003c/span\u003e\u003c/div\u003e\r\n\u003ch3 style\u003d\"font-family:Arial,Verdana,sans-serif\"\u003e\u003ca name\u003d\"TOC-Diagnose-especially-flaky-tests\" /\u003e\u003cfont size\u003d\"3\"\u003e4. Diagnose especially flaky tests\u003c/font\u003e\u003c/h3\u003e\r\n\u003cdiv style\u003d\"font-family:Arial,Verdana,sans-serif\"\u003e\r\n\u003col\u003e\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eLoad the\u003ca href\u003d\"http://test-results.appspot.com/dashboards/overview.html#group\u003d%40ToT%20Blink\u0026amp;flipCount\u003d12\"\u003e flakiness dashboard\u003c/a\u003e\u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003e\u003cspan style\u003d\"font-size:10pt\"\u003eTweak the flakiness threshold to the desired level of flakiness. \u003c/span\u003e\u003c/li\u003e\r\n\u003cli\u003eClick on \"layout-tests\" to get that list of flaky tests.\u003c/li\u003e\r\n\u003cli\u003eDiagnose the source of flakiness for that test.\u003c/li\u003e\r\n\u003c/ol\u003e\u003ch3\u003e\u003ca name\u003d\"TOC-5.-Fix-any-line-in-TestExpectations\" /\u003e5. Fix any line in TestExpectations\u003c/h3\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\u003c/div\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8455202019639247095"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8455202019639247095"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8455202019639247095"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"layout-test-contest"},"sites$revision":{"$t":"18"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5612752149867797547"},"published":{"$t":"2013-10-14T18:34:09.753Z"},"updated":{"$t":"2013-10-14T18:34:11.190Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T18:34:09.753Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Mon Oct 14 2013 11:34:09 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-mon-oct-14-2013-11-34-09-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5612752149867797547"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5612752149867797547"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5612752149867797547"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-mon-oct-14-2013-11-34-09-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/856758833137528123"},"published":{"$t":"2013-10-14T17:26:43.963Z"},"updated":{"$t":"2013-10-14T17:26:44.155Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T17:26:43.963Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Mon Oct 14 2013 10:26:43 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-mon-oct-14-2013-10-26-43-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/856758833137528123"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/856758833137528123"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/856758833137528123"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-mon-oct-14-2013-10-26-43-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/883112698360195072"},"published":{"$t":"2013-10-14T17:26:17.287Z"},"updated":{"$t":"2013-10-14T17:26:17.604Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T17:26:17.287Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Mon Oct 14 2013 10:26:17 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-mon-oct-14-2013-10-26-17-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/883112698360195072"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/883112698360195072"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/883112698360195072"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-mon-oct-14-2013-10-26-17-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/531489774127909646"},"published":{"$t":"2013-10-14T17:24:44.764Z"},"updated":{"$t":"2013-10-14T17:24:45.011Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T17:24:44.764Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Mon Oct 14 2013 10:24:44 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-mon-oct-14-2013-10-24-44-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/531489774127909646"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/531489774127909646"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/531489774127909646"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-mon-oct-14-2013-10-24-44-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8723322042284913122"},"published":{"$t":"2013-10-14T17:24:06.212Z"},"updated":{"$t":"2013-10-14T17:24:06.542Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T17:24:06.212Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Mon Oct 14 2013 10:24:05 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-mon-oct-14-2013-10-24-05-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8723322042284913122"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8723322042284913122"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8723322042284913122"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-mon-oct-14-2013-10-24-05-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/6769207420785476090"},"published":{"$t":"2013-10-14T17:23:23.160Z"},"updated":{"$t":"2013-10-14T17:23:23.379Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-14T17:23:23.160Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Mon Oct 14 2013 10:23:23 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-mon-oct-14-2013-10-23-23-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/6769207420785476090"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6769207420785476090"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/6769207420785476090"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-mon-oct-14-2013-10-23-23-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/3071267525898729358"},"published":{"$t":"2013-10-11T23:48:10.046Z"},"updated":{"$t":"2013-10-11T23:48:10.271Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-11T23:48:10.046Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Fri Oct 11 2013 16:48:09 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-fri-oct-11-2013-16-48-09-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/3071267525898729358"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3071267525898729358"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3071267525898729358"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-fri-oct-11-2013-16-48-09-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/2992150002350236289"},"published":{"$t":"2013-10-11T22:48:58.046Z"},"updated":{"$t":"2013-10-11T22:49:00.832Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-11T22:48:58.046Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Fri Oct 11 2013 15:48:57 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-fri-oct-11-2013-15-48-57-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/2992150002350236289"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2992150002350236289"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/2992150002350236289"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-fri-oct-11-2013-15-48-57-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8909926547334203895"},"published":{"$t":"2013-10-11T06:24:19.062Z"},"updated":{"$t":"2013-10-11T06:24:19.112Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-11T06:24:19.062Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"c720-chromebook-innards.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/8909926547334203895"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9041942356411587249"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook/c720-chromebook-innards.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8909926547334203895"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8909926547334203895"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8909926547334203895"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/8909926547334203895"}],"author":[{"name":{"$t":"David Parker"},"email":{"$t":"dparker@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7896339279667240887"},"published":{"$t":"2013-10-11T06:17:11.240Z"},"updated":{"$t":"2013-10-11T06:17:11.250Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-11T06:17:11.240Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"c720-chromebook-innards-small.png"},"summary":{},"content":{"type":"image/png","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/7896339279667240887"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/9041942356411587249"},{"rel":"alternate","type":"image/png","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/developer-information-for-chrome-os-devices/acer-c720-chromebook/c720-chromebook-innards-small.png"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7896339279667240887"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7896339279667240887"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7896339279667240887"},{"rel":"edit-media","type":"image/png","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/7896339279667240887"}],"author":[{"name":{"$t":"David Parker"},"email":{"$t":"dparker@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/692006239805581401"},"published":{"$t":"2013-10-11T00:28:08.801Z"},"updated":{"$t":"2013-10-11T00:28:09.569Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-11T00:28:08.801Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 10 2013 17:28:08 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-10-2013-17-28-08-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/692006239805581401"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/692006239805581401"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/692006239805581401"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-10-2013-17-28-08-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/8318720744031651742"},"published":{"$t":"2013-10-10T23:56:34.435Z"},"updated":{"$t":"2013-10-10T23:56:34.731Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-10T23:56:34.435Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 10 2013 16:56:34 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-10-2013-16-56-34-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/8318720744031651742"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8318720744031651742"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/8318720744031651742"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-10-2013-16-56-34-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7896788664606447529"},"published":{"$t":"2013-10-10T23:36:05.884Z"},"updated":{"$t":"2013-10-10T23:36:06.025Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-10T23:36:05.884Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 10 2013 16:36:05 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-10-2013-16-36-05-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7896788664606447529"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7896788664606447529"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7896788664606447529"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-10-2013-16-36-05-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5941936980190989698"},"published":{"$t":"2013-10-10T21:40:46.585Z"},"updated":{"$t":"2013-10-10T21:40:46.833Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-10T21:40:46.585Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Thu Oct 10 2013 14:40:46 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-thu-oct-10-2013-14-40-46-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5941936980190989698"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5941936980190989698"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5941936980190989698"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-thu-oct-10-2013-14-40-46-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/927275934696181126"},"published":{"$t":"2013-10-09T21:50:58.431Z"},"updated":{"$t":"2013-10-09T21:50:58.573Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-09T21:50:58.431Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Wed Oct 09 2013 14:50:58 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003edpranke\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-wed-oct-09-2013-14-50-58-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/927275934696181126"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/927275934696181126"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/927275934696181126"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-wed-oct-09-2013-14-50-58-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/5115336323832426309"},"published":{"$t":"2013-10-09T17:51:59.102Z"},"updated":{"$t":"2013-10-09T17:51:59.111Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-09T17:51:59.102Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#attachment","label":"attachment"}],"title":{"$t":"cryptospecs.webp"},"summary":{},"content":{"type":"image/webp","src":"https://a77db9aa-a-7b23c8ea-s-sites.googlegroups.com/feeds/media/content/chromium.org/dev/5115336323832426309"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5467815236996308114"},{"rel":"alternate","type":"image/webp","href":"https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/verified-boot-crypto/cryptospecs.webp"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/5115336323832426309"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5115336323832426309"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/5115336323832426309"},{"rel":"edit-media","type":"image/webp","href":"https://sites.google.com/feeds/media/content/chromium.org/dev/5115336323832426309"}],"author":[{"email":{"$t":"gauravsh@chromium.org"}}],"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/7923026794396389158"},"published":{"$t":"2013-10-09T00:18:19.746Z"},"updated":{"$t":"2013-10-09T00:18:19.865Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-09T00:18:19.746Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 08 2013 17:18:19 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003eleviw\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-08-2013-17-18-19-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/7923026794396389158"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7923026794396389158"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/7923026794396389158"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-08-2013-17-18-19-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/1813251678109795354"},"published":{"$t":"2013-10-08T23:56:36.873Z"},"updated":{"$t":"2013-10-08T23:56:36.962Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-08T23:56:36.873Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 08 2013 16:56:36 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003eleviw\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-08-2013-16-56-36-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/1813251678109795354"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1813251678109795354"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/1813251678109795354"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-08-2013-16-56-36-gmt-0700-pdt"},"sites$revision":{"$t":"1"}},{"gd$etag":"\"YD0peyY.\"","id":{"$t":"https://sites.google.com/feeds/content/chromium.org/dev/651664873547430280"},"published":{"$t":"2013-10-08T23:38:45.454Z"},"updated":{"$t":"2013-10-08T23:38:45.530Z"},"app$edited":{"xmlns$app":"http://www.w3.org/2007/app","$t":"2013-10-08T23:38:45.454Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://schemas.google.com/sites/2008#announcement","label":"announcement"}],"title":{"$t":"Updated Leaderboard Tue Oct 08 2013 16:38:45 GMT-0700 (PDT)"},"content":{"type":"xhtml","$t":"\u003cdiv xmlns\u003d\"http://www.w3.org/1999/xhtml\"\u003e\u003ctable cellspacing\u003d\"0\" class\u003d\"sites-layout-name-one-column sites-layout-hbox\"\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd class\u003d\"sites-layout-tile sites-tile-name-content-1\"\u003eTop 5:\u003col\u003e\u003cli\u003erune\u003c/li\u003e\u003cli\u003eeae\u003c/li\u003e\u003cli\u003eadamk\u003c/li\u003e\u003cli\u003eojan\u003c/li\u003e\u003cli\u003eleviw\u003c/li\u003e\u003c/ol\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/tbody\u003e\u003c/table\u003e\u003c/div\u003e"},"link":[{"rel":"http://schemas.google.com/sites/2008#parent","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/3289128834195237337"},{"rel":"alternate","type":"text/html","href":"https://sites.google.com/a/chromium.org/dev/layout-test-contest/layout-test-contest-leaderboard/updated-leaderboard-tue-oct-08-2013-16-38-45-gmt-0700-pdt"},{"rel":"http://schemas.google.com/sites/2008#revision","type":"application/atom+xml","href":"https://sites.google.com/feeds/revision/chromium.org/dev/651664873547430280"},{"rel":"self","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/651664873547430280"},{"rel":"edit","type":"application/atom+xml","href":"https://sites.google.com/feeds/content/chromium.org/dev/651664873547430280"}],"author":[{"name":{"$t":"Julie Parent"},"email":{"$t":"jparent@chromium.org"}}],"sites$pageName":{"$t":"updated-leaderboard-tue-oct-08-2013-16-38-45-gmt-0700-pdt"},"sites$revision":{"$t":"1"}}]}}