diff --git a/AUTHORS b/AUTHORS index cbae519..bcf7465 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -316,6 +316,7 @@ Mark Hahnenberg <mhahnenb@andrew.cmu.edu> Mark Seaborn <mrs@mythic-beasts.com> Martin Bednorz <m.s.bednorz@gmail.com> +Martina Kollarova <martina.kollarova@intel.com> Masahiro Yado <yado.masa@gmail.com> Matheus Bratfisch <matheusbrat@gmail.com> Mathias Bynens <mathias@qiwi.be>
diff --git a/DEPS b/DEPS index 118b290a..d31af62 100644 --- a/DEPS +++ b/DEPS
@@ -34,20 +34,20 @@ 'llvm_url': 'http://src.chromium.org/llvm-project', 'llvm_git': 'https://llvm.googlesource.com', 'webkit_trunk': 'http://src.chromium.org/blink/trunk', - 'webkit_revision': 'e0eac2485a0151a4e0454ec1ad62ee7e9fe01911', # from svn revision 193311 + 'webkit_revision': 'b559582e73c0233840edb4e681dc284b768706fa', # from svn revision 193437 'chromium_git': 'https://chromium.googlesource.com', 'chromiumos_git': 'https://chromium.googlesource.com/chromiumos', 'pdfium_git': 'https://pdfium.googlesource.com', 'skia_git': 'https://skia.googlesource.com', 'boringssl_git': 'https://boringssl.googlesource.com', - 'libvpx_revision': '861f35b01c87a021540aace739cb7415c08e987b', + 'libvpx_revision': '1fff3e3550a605f7edf72280ed8fcaa83eeb586e', 'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac', - 'skia_revision': 'c654e9016a15985ebeb24f94f819d113ad48a251', + 'skia_revision': 'fbcf0bd7ff87a55d978016a686dd7dd8fc32e993', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and V8 without interference from each other. 'v8_branch': 'trunk', - 'v8_revision': 'c817f6989574b4d80e4c68980e3de46acacaade0', + 'v8_revision': 'ca308522aed3a3cd63118b338f4f939f4ad91f82', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling WebRTC # and V8 without interference from each other. @@ -74,7 +74,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '40acdaeb86c516b68e3442f3a008e8d21e514bda', + 'boringssl_revision': 'ef4962f5a38fd68f0b89b67fc5e13da70e4288f6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nss # and whatever else without interference from each other. @@ -129,7 +129,7 @@ Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8', 'src/third_party/crashpad/crashpad': - Var('chromium_git') + '/crashpad/crashpad.git' + '@' + 'e1347a740c051d9a44aa2dd0b9d11067a53e0447', + Var('chromium_git') + '/crashpad/crashpad.git' + '@' + '1baff4ff92fe1a1ead6b88b5f01633a4f0b6b51c', 'src/third_party/trace-viewer': Var('chromium_git') + '/external/trace-viewer.git' + '@' + '07909fe53e549b42634142ef07d1eb970d94b3d3', @@ -210,7 +210,7 @@ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '104f872faf2cd809cdada885a1e39be85e5b3316', 'src/third_party/libjingle/source/talk': - Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'e9dbaf89fd1fbce930e46ed18277c3b49e761dbe', + Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '32d6efbe909b1fec430fa71d9dbc2bbc30c873c2', 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215 @@ -234,7 +234,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '6f9fcb2ba5dcd4a8d1c3e74a5d20ee2d5c00212b', + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '9e4853a2a1222020ac574bb2362d48348e44d220', 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/WATCHLISTS b/WATCHLISTS index d1e8cb8..3a20678 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -625,8 +625,9 @@ '|content/zygote/'\ }, 'scheduler': { - 'filepath': 'cc/scheduler|'\ - 'content/renderer/scheduler' + 'filepath': 'cc/scheduler'\ + '|content/child/scheduler'\ + '|content/renderer/scheduler' }, 'search': { 'filepath': 'chrome/browser/ui/search/',
diff --git a/android_webview/apk/java/AndroidManifest.xml b/android_webview/apk/java/AndroidManifest.xml index 4168410..d9b7c02d2 100644 --- a/android_webview/apk/java/AndroidManifest.xml +++ b/android_webview/apk/java/AndroidManifest.xml
@@ -30,5 +30,7 @@ <provider android:name="com.android.webview.chromium.LicenseContentProvider" android:exported="true" android:authorities="com.android.webview.chromium.LicenseContentProvider" /> + <meta-data android:name="com.android.webview.WebViewLibrary" + android:value="libwebviewchromium.so" /> </application> </manifest>
diff --git a/android_webview/buildbot/OWNERS b/android_webview/buildbot/OWNERS deleted file mode 100644 index 89217ce..0000000 --- a/android_webview/buildbot/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -benm@chromium.org -torne@chromium.org
diff --git a/android_webview/buildbot/aosp_manifest.xml b/android_webview/buildbot/aosp_manifest.xml deleted file mode 100644 index 667c0645..0000000 --- a/android_webview/buildbot/aosp_manifest.xml +++ /dev/null
@@ -1,481 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<manifest> - <remote name="aosp" - fetch=".." - review="https://android-review.googlesource.com/" /> - <default remote="aosp" - sync-j="6" /> - - <project name="platform/frameworks/webview" path="frameworks/webview" revision="a66eee2fb2290adf1240d6f900876451948e019e"/> - - <project groups="device,flo" name="device/asus/deb" revision="f7bd9fa832e3256aa4eb940d1e844f07d966b7ab"/> - <project groups="device,flo" name="device/asus/flo" revision="b0c2235b2bc90ee99f609b31e58eb3afb7f9e070"/> - <project groups="device,flo" name="device/asus/flo-kernel" revision="a9fee327251d98b45e0012dd45358c4318e11bb2"/> - <project groups="device,fugu" name="device/asus/fugu" revision="ec3476d7bc6fc467b10b20b4ba8d6864041dfcf5"/> - <project groups="device,fugu" name="device/asus/fugu-kernel" revision="f3405550c8b134d8bd6e24ce29db7badd1568543"/> - <project groups="device,grouper" name="device/asus/grouper" revision="a70c8231eb0fb1de6c83ac8c4158fbf6edff6af2"/> - <project groups="device,grouper" name="device/asus/tilapia" revision="495f0a9b2064a129af669e9959c2027f984e889c"/> - <project groups="pdk-cw-fs" name="device/common" revision="b143878e855aff96d089c26e99f02879062bdc1b"/> - <project groups="pdk" name="device/generic/arm64" revision="39249053f37b7f9633eb406af3dbedfea7bf8b3e"/> - <project groups="pdk" name="device/generic/armv7-a-neon" revision="2a96372d80c693fc28b29328b3e86b65cab9189b"/> - <project groups="pdk" name="device/generic/common" revision="11c092a6cbfcf6207f07a9a8e3398e747e7f5461"/> - <project groups="pdk" name="device/generic/goldfish" revision="8e0631aab1cdc64d01d176cfaf5ca721cbe3f24d"/> - <project groups="pdk" name="device/generic/mini-emulator-arm64" revision="743dd408af5c662761bafc05eacdb18ade88cf3a"/> - <project groups="pdk" name="device/generic/mini-emulator-armv7-a-neon" revision="94dbaf7049a7947e51d8ec3c62634e3acc29b590"/> - <project groups="pdk" name="device/generic/mini-emulator-mips" revision="3fdb24de40ca27da9a86f10f31314f2a13259db5"/> - <project groups="pdk" name="device/generic/mini-emulator-x86" revision="65d59e2be2cfd713513a05d80a0f75794ab60579"/> - <project groups="pdk" name="device/generic/mini-emulator-x86_64" revision="673aae8bd65d9708821c4062f6a0364a859e7ae4"/> - <project groups="pdk" name="device/generic/mips" revision="9ade14663b97581a4297047e359ca1cae9ac8399"/> - <project name="device/generic/qemu" revision="3f0d50b7e7d8a899bab15f5cbaeb0f51d1eea4d4"/> - <project groups="pdk" name="device/generic/x86" revision="26d680b5edde00120726a05c204e97ddef3d246a"/> - <project groups="pdk" name="device/generic/x86_64" revision="138339be1da9b0f34befe3751b0bae874d7253db"/> - <project groups="device" name="device/google/accessory/arduino" revision="abc5159a3ca9dbb5c7e364a1eab99901a4440ac5"/> - <project groups="device" name="device/google/accessory/demokit" revision="7dfe7f89a3b174709c773fe319531006e46440d9"/> - <project groups="device,fugu" name="device/google/atv" revision="1fd2c3361c21d1e67065e50f84d47524c0e1bb5e"/> - <project groups="device,flounder" name="device/htc/flounder" revision="dbb6d764d29429b3a0584f525647ff18af68664b"/> - <project groups="device,flounder" name="device/htc/flounder-kernel" revision="8a4f5f783201d9acb0a628fdd2a313e508917e49"/> - <project groups="device,hammerhead" name="device/lge/hammerhead" revision="1edcc542b2f40c17147b6fdb7c3b30977e6f1e28"/> - <project groups="device,hammerhead" name="device/lge/hammerhead-kernel" revision="d9dc941819bcc9ceb005b330987f7f7ba1dc46a9"/> - <project groups="device,mako" name="device/lge/mako" revision="5b2d9248e0e5787cf5f1b08925da0b545093c58c"/> - <project groups="device,mako" name="device/lge/mako-kernel" revision="7bf237bdf8a8c6d516219dc09b3bc114aa0e863d"/> - <project groups="device,shamu" name="device/moto/shamu" revision="f299008844514408b95f73b371f5442399603693"/> - <project groups="device,shamu" name="device/moto/shamu-kernel" revision="78c6a1b3c1af29c82e094c5ace530a1897ecf1f5"/> - <project groups="pdk" name="device/sample" revision="bad2c94542e03d66acceae7a46c383eb9f30911a"/> - <project groups="device,manta" name="device/samsung/manta" revision="90f4857ca8b2812543b6a1da1de23371dfb748b0"/> - <project groups="pdk" name="platform/abi/cpp" path="abi/cpp" revision="36b381298a4efb7c293d394d8b1acbda68230989"/> - <project groups="pdk" name="platform/art" path="art" revision="bbba809a680fa7ad030da351e92786848d63b9bf"/> - <project groups="pdk" name="platform/bionic" path="bionic" revision="8408d7efacd83c1813501954d3e199b63f350778"/> - <project groups="pdk-cw-fs" name="platform/bootable/bootloader/legacy" path="bootable/bootloader/legacy" revision="3c491d6efb8ff2534a6934702760a6273f197918"/> - <project groups="pdk" name="platform/bootable/recovery" path="bootable/recovery" revision="c43b17f0adac1092e221ce6166ca8bc464090525"/> - <project groups="pdk,tradefed" name="platform/build" path="build" revision="0db9ea923309f514a3216826593b325cffcfbbbf"> - <copyfile dest="Makefile" src="core/root.mk"/> - </project> - <project groups="cts,pdk-cw-fs" name="platform/cts" path="cts" revision="27c531b3a156a49ec133570e00edb0030d84bb46"/> - <project groups="pdk-cw-fs" name="platform/dalvik" path="dalvik" revision="c95485186a5075e7568198c47e7290980353ce1c"/> - <project name="platform/developers/build" path="developers/build" revision="f6fd7f242a1f5ac51840ea8d02e24f56fd862f11"/> - <project name="platform/developers/demos" path="developers/demos" revision="7c700e80b902c8f7778ffd63c287ac5710fd69ef"/> - <project name="platform/developers/docs" path="developers/docs" revision="c0b835ddd9acc27176dc9a0f7d1aa2faf5d51806"/> - <project name="platform/developers/samples/android" path="developers/samples/android" revision="1b1d8b0c3f29b2520554602eb72c0e9456efa5ac"/> - <project groups="pdk-cw-fs" name="platform/development" path="development" revision="409b471e481421d623c0c6f88feb11e66a1dc987"/> - <project groups="pdk-cw-fs" name="platform/docs/source.android.com" path="docs/source.android.com" revision="6b674a1d825bb63044aa7547cfdd36deb640b7d4"/> - <project groups="pdk" name="platform/external/aac" path="external/aac" revision="66091e46d7aae1b45ed96f5f39274954a296db71"/> - <project groups="pdk-cw-fs" name="platform/external/android-clat" path="external/android-clat" revision="fee9afb1a5d9f7f5df0c79e29368c61d7da16fb8"/> - <project groups="pdk-cw-fs" name="platform/external/ant-glob" path="external/ant-glob" revision="0f189400fd2a36bf11bfb058e7f3917eb7ed163a"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/antlr" path="external/antlr" revision="47997265eeb7d954a32ece693bbe6dab740872dd"/> - <project groups="pdk-cw-fs" name="platform/external/apache-harmony" path="external/apache-harmony" revision="537ad57d762c8e57d847337f377b9606bc2874f7"/> - <project groups="pdk-cw-fs" name="platform/external/apache-http" path="external/apache-http" revision="3db33b69ecf386804af1710935f64a8eaa0c6253"/> - <project groups="pdk-cw-fs" name="platform/external/apache-qp" path="external/apache-qp" revision="64ea622b23e6612eb8e7dcae6bfd4314beb022a8"/> - <project groups="pdk-cw-fs" name="platform/external/apache-xml" path="external/apache-xml" revision="ce8a93585b71d80730020e0cd945442b05dd606b"/> - <project groups="pdk-cw-fs" name="platform/external/arduino" path="external/arduino" revision="60f21b2e195defce0d56fa789ece5cb04a34e37b"/> - <project groups="pdk" name="platform/external/bison" path="external/bison" revision="c2418b886165add7f5a31fc5609f0ce2d004a90e"/> - <project groups="pdk-cw-fs" name="platform/external/blktrace" path="external/blktrace" revision="d345431f16b8f76f30a58193ff2b26d5853e1109"/> - <project groups="pdk" name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="51dcba7a9a9860eb1f6a44ae268cbf24e3411694"/> - <project groups="pdk" name="platform/external/bouncycastle" path="external/bouncycastle" revision="bd63be61caf85120ee69cda508a35580a230d57c"/> - <project groups="pdk" name="platform/external/bsdiff" path="external/bsdiff" revision="6f503758fad2cbcf8359e8f0af32e4d79a2a48ae"/> - <project groups="pdk" name="platform/external/bzip2" path="external/bzip2" revision="1cb636bd8e9e5cdfd5d5b2909a122f6e80db62de"/> - <project groups="pdk-cw-fs" name="platform/external/ceres-solver" path="external/ceres-solver" revision="79397c21138f54fcff6ec067b44b847f1f7e0e98"/> - <project groups="pdk" name="platform/external/checkpolicy" path="external/checkpolicy" revision="c24d01d337ab3d449dd21f50adb882af1aae3f66"/> - <project name="platform/external/chromium-libpac" path="external/chromium-libpac" revision="338f7285d7e3b6cec739fde87af9a02330155a12"/> - <project groups="pdk" name="platform/external/chromium-trace" path="external/chromium-trace" revision="a4c64913fc7e0930ad3aa40415c5d467e2cc3b8b"/> - <project groups="pdk" name="platform/external/clang" path="external/clang" revision="8b939a0498b8d24f4a5d7c6e6ac94ddba75ee933"/> - <project name="platform/external/cmockery" path="external/cmockery" revision="bdd62c531bbdea115a3a7e71bba91c19dd319cc4"/> - <project groups="pdk" name="platform/external/compiler-rt" path="external/compiler-rt" revision="45badb4fbfc53b8bebbcb431cb4b9807184da901"/> - <project groups="pdk-cw-fs" name="platform/external/conscrypt" path="external/conscrypt" revision="ba3e8b69ec8b9f29cf7f9ace05cae83721945ff0"/> - <project name="platform/external/deqp" path="external/deqp" revision="7665e4ff5452f9fc261434f98484728a233ef452"/> - <project groups="pdk-cw-fs" name="platform/external/dexmaker" path="external/dexmaker" revision="00bf6870ff223dec90d9fac39e5dfb464a59f6de"/> - <project groups="pdk-cw-fs" name="platform/external/dhcpcd" path="external/dhcpcd" revision="4c31886d40a73811283e83bfdaf787bf62ec8cf9"/> - <project groups="pdk" name="platform/external/dnsmasq" path="external/dnsmasq" revision="f0f842adf0d07ddc6d3338b7098310756b7c6f35"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/doclava" path="external/doclava" revision="8566f2d5a4aebe02c2324b40b29d351113cd976a"/> - <project groups="pdk-cw-fs" name="platform/external/droiddriver" path="external/droiddriver" revision="270f805bf930fb13c6a314c130de017298012eb8"/> - <project groups="pdk" name="platform/external/e2fsprogs" path="external/e2fsprogs" revision="2ca3c65991609bb5b48004ec3c7a66f6b417beed"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/easymock" path="external/easymock" revision="c9a234086537e5fd820b110bbd99e3cdc695004c"/> - <project groups="pdk-cw-fs" name="platform/external/eclipse-basebuilder" path="external/eclipse-basebuilder" revision="6134da6347cc997e0cf2921aaadfb46f21c05d85"/> - <project groups="pdk-cw-fs" name="platform/external/eclipse-windowbuilder" path="external/eclipse-windowbuilder" revision="a5f3ee137e94737538ec3bdf9b3716765d178c17"/> - <project groups="pdk-cw-fs" name="platform/external/eigen" path="external/eigen" revision="7faaa9f3f0df9d23790277834d426c3d992ac3ba"/> - <project groups="pdk" name="platform/external/elfutils" path="external/elfutils" revision="b85bc28b290a7186560a94cfbaafef09e4aafa93"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/emma" path="external/emma" revision="daacd02a6b9f7a3e82bdf1cc5b84db85ed59edb1"/> - <project groups="pdk-cw-fs" name="platform/external/esd" path="external/esd" revision="224a67f2683a7ee997179fc5dd16115e39987b0f"/> - <project groups="pdk" name="platform/external/expat" path="external/expat" revision="907ec055718996baf36961e7f47f8447e49b3865"/> - <project groups="pdk-cw-fs" name="platform/external/eyes-free" path="external/eyes-free" revision="16bd4c7a4d1bfe229068b637614dad7c48dd2ceb"/> - <project groups="pdk" name="platform/external/f2fs-tools" path="external/f2fs-tools" revision="100ea9f321b92fa1e15889ec0ef72b6b8929459d"/> - <project groups="pdk" name="platform/external/fdlibm" path="external/fdlibm" revision="e240b95f6f3127af5f23c6be77083255392bdf8a"/> - <project name="platform/external/fio" path="external/fio" revision="b287c3293081dd98182a026a15e63536148b3287"/> - <project groups="pdk" name="platform/external/flac" path="external/flac" revision="457fe12432caac0de0e430bb976dab681b3ae1a2"/> - <project name="platform/external/fonttools" path="external/fonttools" revision="5b2a84657752801e007ee075e10beda0afde0ae3"/> - <project groups="pdk" name="platform/external/freetype" path="external/freetype" revision="9c745321260bb728ab1cd1c8fd5f075854b2ad49"/> - <project groups="pdk-cw-fs" name="platform/external/fsck_msdos" path="external/fsck_msdos" revision="17a1471db8c528cd9d44ec4385d2eb3614138856"/> - <project groups="pdk" name="platform/external/gcc-demangle" path="external/gcc-demangle" revision="9290490959af27ad6815a7d660f1d98509c370e6"/> - <project groups="pdk-cw-fs" name="platform/external/genext2fs" path="external/genext2fs" revision="e11a9c7fe6f1cef99aad2f25afaea37b72fe9f93"/> - <project groups="pdk-cw-fs,qcom_msm8x26" name="platform/external/giflib" path="external/giflib" revision="b5a8e44648685070f146ff8456d36013c502f7a1"/> - <project name="platform/external/glide" path="external/glide" revision="3dddc8773c50852bc592b8bc32d92eb153ce8dba"/> - <project groups="pdk-cw-fs" name="platform/external/google-diff-match-patch" path="external/google-diff-match-patch" revision="cecbe12841337860291c2d6a5728b681ec5fca2a"/> - <project groups="pdk-cw-fs" name="platform/external/google-fonts/carrois-gothic-sc" path="external/google-fonts/carrois-gothic-sc" revision="0062a10458d4c357f3082d66bcb129d11913aaae"/> - <project groups="pdk-cw-fs" name="platform/external/google-fonts/coming-soon" path="external/google-fonts/coming-soon" revision="2c5cb418c690815545bbb0316eae5fd33b9fc859"/> - <project groups="pdk-cw-fs" name="platform/external/google-fonts/cutive-mono" path="external/google-fonts/cutive-mono" revision="bce2136662854076023066602526ba299e6556b2"/> - <project groups="pdk-cw-fs" name="platform/external/google-fonts/dancing-script" path="external/google-fonts/dancing-script" revision="7b6623bd54cee3e48ae8a4f477f616366643cc78"/> - <project name="platform/external/google-tv-pairing-protocol" path="external/google-tv-pairing-protocol" revision="450c5ad6a6efc16de0383f5aecdfdeac2736ca30"/> - <project groups="pdk" name="platform/external/gtest" path="external/gtest" revision="db985372bfc2a91ddd62b04a743f479ae4ae2a77"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/guava" path="external/guava" revision="5e6db342fc75b1945298142530f2d1d1861bce73"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/hamcrest" path="external/hamcrest" revision="15e01a79e1b28255229f4d3aefc4b030c261afd1"/> - <project groups="pdk-cw-fs,qcom_msm8x26" name="platform/external/harfbuzz_ng" path="external/harfbuzz_ng" revision="b6f5a05cd719668405ec29e587f16d3d59ebd4f4"/> - <project groups="pdk" name="platform/external/icu" path="external/icu" revision="7e109695da3020b6081728b66a68886a0b8d33c2"/> - <project groups="pdk" name="platform/external/iproute2" path="external/iproute2" revision="eae80e8c17b6292cff0b10002bbc4398fc93c435"/> - <project groups="pdk-cw-fs" name="platform/external/ipsec-tools" path="external/ipsec-tools" revision="b229bdf5e3530ebbd04da6e1924aca629cb77b7d"/> - <project groups="pdk-cw-fs" name="platform/external/iptables" path="external/iptables" revision="94ccd7362d9e5f8f422ee54215af9952ed41a274"/> - <project groups="pdk-cw-fs" name="platform/external/iputils" path="external/iputils" revision="1c7c426ab377c3a005a36d612ebbb16de86fb7d4"/> - <project groups="pdk-cw-fs" name="platform/external/jack" path="external/jack" revision="5ceb2025ac5d25ed48183ac2d3dac4691fe761fb"/> - <project groups="pdk" name="platform/external/jarjar" path="external/jarjar" revision="b9c9541421a9b7ffae2b0de6679438741ae9bbfe"/> - <project groups="pdk-cw-fs" name="platform/external/javasqlite" path="external/javasqlite" revision="9f4bd3c5c946dcedfad76df812cb24a2829e4193"/> - <project groups="pdk-cw-fs" name="platform/external/javassist" path="external/javassist" revision="9566207cff5871c672fac1f0d4332d93292036d7"/> - <project groups="pdk-cw-fs" name="platform/external/jdiff" path="external/jdiff" revision="e4694302d6a3786c64d954e0b3cf42786283bd3c"/> - <project groups="pdk" name="platform/external/jemalloc" path="external/jemalloc" revision="875f4f09810b9a2af5081972fd1f9dda19ffae5d"/> - <project groups="pdk" name="platform/external/jhead" path="external/jhead" revision="afe9f55ee6ba3eaee02e7b13809a534ebe98d34a"/> - <project groups="notdefault,tradefed" name="platform/external/jline" path="external/jline" revision="cad954e739ba001fe3531c31202a7d726c00357e"/> - <project groups="pdk-cw-fs" name="platform/external/jmdns" path="external/jmdns" revision="f4eb7466d5c09098f9dc54137ed3235e3c43fc9f"/> - <project groups="pdk" name="platform/external/jpeg" path="external/jpeg" revision="57cc16e38e6461da4317c285eec61c3265e516bf"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/jsilver" path="external/jsilver" revision="739060b01245f1dc5f1800949b3c30c291253cff"/> - <project groups="pdk" name="platform/external/jsmn" path="external/jsmn" revision="27b5a35db0630b86791fa037a12da7b37c2aab49"/> - <project groups="pdk-cw-fs" name="platform/external/jsoncpp" path="external/jsoncpp" revision="7029472cdc862c8bb870340332f86f983cb17c3d"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/jsr305" path="external/jsr305" revision="a82868820d6350811b9ddfde4bf8ed5016084269"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/junit" path="external/junit" revision="191f8c8707a105d683fa0fa3ff6f645633f1d463"/> - <project groups="pdk-cw-fs" name="platform/external/kernel-headers" path="external/kernel-headers" revision="fdcbe82d7a1b2b60c30bdea1ef9c0967ab9550c5"/> - <project groups="pdk-cw-fs" name="platform/external/ksoap2" path="external/ksoap2" revision="deba639927618694aa92b987654f0279b7c7d3fa"/> - <project groups="pdk-cw-fs" name="platform/external/libcap-ng" path="external/libcap-ng" revision="52447887e50b49f33f959077c31232edff6659d8"/> - <project groups="pdk" name="platform/external/libcxx" path="external/libcxx" revision="4ba8d41e2d3b08f7317d34656468b42718f7d16f"/> - <project groups="pdk" name="platform/external/libcxxabi" path="external/libcxxabi" revision="9623d0dca99755d5bbf4623c5513b060bb3a0be4"/> - <project name="platform/external/libedit" path="external/libedit" revision="92d2359bcffabfcca85c64eb4908556aa69ef96a"/> - <project groups="pdk-cw-fs" name="platform/external/libexif" path="external/libexif" revision="fa0c1e7d954230cd29d896e6015314b2f68ad7bd"/> - <project groups="pdk" name="platform/external/libgsm" path="external/libgsm" revision="50761abed8f4734970874165b386cfd4d9599db4"/> - <project name="platform/external/libhevc" path="external/libhevc" revision="fee3b565f9bdcab93cce9661670da9cb95e6cdbd"/> - <project groups="pdk" name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/> - <project groups="pdk-cw-fs" name="platform/external/libmtp" path="external/libmtp" revision="7075348937f6a8c9d9211942fcb6c376f4227776"/> - <project groups="pdk" name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="97dff702b35992d4df2b6e479de857c57835da54"/> - <project groups="pdk" name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="76f8fa7177767cb377f9212e207e3ac16f9b8d48"/> - <project groups="pdk" name="platform/external/libnl" path="external/libnl" revision="f6c30c401b0a9608bbf8c88a4408f3d94b8f7e51"/> - <project groups="pdk" name="platform/external/libogg" path="external/libogg" revision="ec0b24fb1468abe37be4164a6feb16568e036bde"/> - <project groups="pdk" name="platform/external/libopus" path="external/libopus" revision="1391dbf0ccd121ce7a49d30e2142d36c8d404990"/> - <project groups="pdk,pdk-cw-fs" name="platform/external/libpcap" path="external/libpcap" revision="9dab0cd7430a4d23e0a7752fb13b941692171c3d"/> - <project groups="pdk-cw-fs" name="platform/external/libphonenumber" path="external/libphonenumber" revision="eec8af34d3129d0f37c45ff8a82b4212724a6d79"/> - <project groups="pdk" name="platform/external/libpng" path="external/libpng" revision="094e181e79a3d6c23fd005679025058b7df1ad6c"/> - <project groups="pdk-cw-fs" name="platform/external/libseccomp-helper" path="external/libseccomp-helper" revision="e87019943a8b5a7cd0880910f671c37b240d5754"/> - <project groups="pdk" name="platform/external/libselinux" path="external/libselinux" revision="716c74b0c1d76ec904de74d6905bd5f1edfd91e1"/> - <project groups="pdk" name="platform/external/libsepol" path="external/libsepol" revision="a0e2379329882674721528199ed1dcdbc5bb17b4"/> - <project groups="pdk-cw-fs" name="platform/external/libssh2" path="external/libssh2" revision="2bb40f2445cab3ba588efb29e1835cdba2b27248"/> - <project groups="pdk" name="platform/external/libunwind" path="external/libunwind" revision="6c61dc81f7edea4f2bf0256ed3b0d11459dec68f"/> - <project groups="pdk-cw-fs" name="platform/external/libusb" path="external/libusb" revision="3a36cef7ef847d3839090a7c98eb961a602af55b"/> - <project groups="pdk-cw-fs" name="platform/external/libusb-compat" path="external/libusb-compat" revision="6d4ab8939e4784b2b6eb63d992cc4d44f953bb41"/> - <project groups="pdk-cw-fs" name="platform/external/libutf" path="external/libutf" revision="9d00b26b4a6fbdf65f4adcd841e9d885d9102b94"/> - <project groups="pdk-cw-fs" name="platform/external/libvorbis" path="external/libvorbis" revision="de559619fd4dd0d2d9608436696fd44bdf74eba8"/> - <project groups="pdk" name="platform/external/libvpx" path="external/libvpx" revision="acfe8bb381dd96f2a1cfe44c882ecd06fbce27f1"/> - <project groups="pdk-cw-fs" name="platform/external/libxml2" path="external/libxml2" revision="092a4128310076d918a20d09d48e6b86a8cd38b0"/> - <project groups="libyuv,pdk-cw-fs" name="platform/external/libyuv" path="external/libyuv" revision="482a582884351288fb701532359652970b1ba7c0"/> - <project groups="pdk-cw-fs" name="platform/external/linux-tools-perf" path="external/linux-tools-perf" revision="f608ab242d9b37e4b4c087314806071202d71f41"/> - <project groups="pdk-cw-fs" name="platform/external/littlemock" path="external/littlemock" revision="a3ea6bf9e6fcf63b69f5635b2ecc1fbd9a9a4dfc"/> - <project groups="pdk-cw-fs" name="platform/external/lldb" path="external/lldb" revision="8aaa52329ade20107fe28af7085b0a1f395816a8"/> - <project groups="pdk" name="platform/external/llvm" path="external/llvm" revision="d2327b22152ced7bc46dc629fc908959e8a52d03"/> - <project groups="pdk-cw-fs" name="platform/external/ltrace" path="external/ltrace" revision="10ffb54609942b390bb9a65964f62425b04df53f"/> - <project groups="pdk" name="platform/external/lzma" path="external/lzma" revision="b473eaa2840cccf2fef15d53f00bccf92c41b615"/> - <project groups="pdk-cw-fs" name="platform/external/markdown" path="external/markdown" revision="6f2e3554ae38cc90518d32e02cb57d05988270a6"/> - <project groups="pdk" name="platform/external/mdnsresponder" path="external/mdnsresponder" revision="a413bce2d767d5b0810016f9b49a69c1e4be2b2f"/> - <project groups="pdk-cw-fs" name="platform/external/mesa3d" path="external/mesa3d" revision="cfa14c46594a66e3f1b6b50b65b5e9f4fa6302a5"/> - <project groups="pdk-cw-fs" name="platform/external/messageformat" path="external/messageformat" revision="fb716cce89ee080907bb5d43dfc84a657e4e5282"/> - <project groups="pdk" name="platform/external/mksh" path="external/mksh" revision="a1c1f910f501fd658f7b2bea133bd47cb8d2395d"/> - <project groups="pdk-cw-fs" name="platform/external/mockito" path="external/mockito" revision="c7d7be3cdbefd99229903414cf71308f47973aa5"/> - <project groups="pdk-cw-fs" name="platform/external/mockwebserver" path="external/mockwebserver" revision="7f9280b5b6ff3532ef27d4f938aa2e6bbc895473"/> - <project groups="pdk-cw-fs" name="platform/external/mp4parser" path="external/mp4parser" revision="16051e950485c6b62127c0446a760111de1a0cb9"/> - <project groups="pdk-cw-fs" name="platform/external/mtpd" path="external/mtpd" revision="5ea8006691664b7e6d46d6a6dc889eac91b7fe37"/> - <project name="platform/external/nanohttpd" path="external/nanohttpd" revision="8d6a97830abf9685bc0724c24766c8f9704aacd2"/> - <project name="platform/external/nanopb-c" path="external/nanopb-c" revision="7ef855e462b9a18b7d330e4b40f350164a6ad9da"/> - <project groups="pdk-cw-fs" name="platform/external/naver-fonts" path="external/naver-fonts" revision="d5210212745194f3a2661fb65e0675ce9665b9b1"/> - <project groups="pdk-cw-fs" name="platform/external/netcat" path="external/netcat" revision="444644cfa9a2f3002863caa168fb2d6b34dfd1e8"/> - <project groups="pdk-cw-fs" name="platform/external/netperf" path="external/netperf" revision="27ffe986a2933b1ff0eecbcc51a807d130e254ec"/> - <project groups="pdk-cw-fs" name="platform/external/neven" path="external/neven" revision="ab02f818aa312f0795152449c29cb994f72e4891"/> - <project groups="pdk-cw-fs" name="platform/external/nfacct" path="external/nfacct" revision="6f7aae0264821b44e9fe80fb5596c525d3e2f475"/> - <project groups="pdk-cw-fs" name="platform/external/nist-pkits" path="external/nist-pkits" revision="2c243d61d94b93eaef6fd5e0f727c9a2be838338"/> - <project groups="pdk-cw-fs" name="platform/external/nist-sip" path="external/nist-sip" revision="b23dbfce7ea84c39cea75b612868a5832cb9af2b"/> - <project groups="pdk" name="platform/external/noto-fonts" path="external/noto-fonts" revision="7b756aa1520f938b31b304746766b681d4b33f00"/> - <project groups="pdk-cw-fs" name="platform/external/oauth" path="external/oauth" revision="bc170f58de82000ed6460f111686a850a1890c07"/> - <project groups="pdk-cw-fs" name="platform/external/objenesis" path="external/objenesis" revision="2a7655c0d503fcf5989098f65bf89eae78c32e5a"/> - <project groups="pdk-cw-fs" name="platform/external/okhttp" path="external/okhttp" revision="fadae63ef6b2d35eec5c11700a340304a1fd0251"/> - <project groups="pdk-cw-fs" name="platform/external/opencv" path="external/opencv" revision="fc68457d6ba93570aaebf0706a9b2567eaea27c1"/> - <project groups="pdk" name="platform/external/openssl" path="external/openssl" revision="e0b66eee8ef672acbd3605ecf7b0899924ca3a17"/> - <project groups="pdk-cw-fs" name="platform/external/oprofile" path="external/oprofile" revision="3722f1053f4cab90c4daf61451713a2d61d79c71"/> - <project name="platform/external/owasp/sanitizer" path="external/owasp/sanitizer" revision="bbfb25464ff30c5a62dce351d719a8c533afb2a3"/> - <project groups="pdk-cw-fs" name="platform/external/pcre" path="external/pcre" revision="1dceafb0c217395f704290bc3f176d5f008b791c"/> - <project groups="pdk-cw-fs" name="platform/external/pdfium" path="external/pdfium" revision="86957661fc29ce82c3101107f95a11d1f9e59932"/> - <project groups="pdk-cw-fs" name="platform/external/pixman" path="external/pixman" revision="0df1724cbd2a9155d34c4ce5739ea29e18b33b52"/> - <project groups="pdk-cw-fs" name="platform/external/ppp" path="external/ppp" revision="8b58d9bd02e2c55f547fafbe9ba55b1160665761"/> - <project groups="pdk-java,tradefed" name="platform/external/proguard" path="external/proguard" revision="9961286c06c25cd03464d3e2b00bd9b9dedf96ba"/> - <project groups="pdk" name="platform/external/protobuf" path="external/protobuf" revision="4353bbc88f513a3c8863cc5b30e765dd5530faa1"/> - <project groups="pdk-cw-fs" name="platform/external/qemu" path="external/qemu" revision="21d4b2c964cf70919b041028af290abd3a3cd64a"/> - <project groups="pdk-cw-fs" name="platform/external/qemu-pc-bios" path="external/qemu-pc-bios" revision="20349dae98d7de09a7e390d4a706c64f1db6edc2"/> - <project groups="pdk-cw-fs" name="platform/external/regex-re2" path="external/regex-re2" revision="9a16eac809c3bbb746f055b38d4e0d5c4f228c73"/> - <project groups="pdk-cw-fs" name="platform/external/replicaisland" path="external/replicaisland" revision="99e2e54c5d036048caf09bb05eea0969de093104"/> - <project groups="pdk-cw-fs" name="platform/external/robolectric" path="external/robolectric" revision="d9d53068f24c9af1a332986dd196c163b3ca897c"/> - <project groups="pdk" name="platform/external/safe-iop" path="external/safe-iop" revision="aa0725fb1da35e47676b6da30009322eb5ed59be"/> - <project groups="pdk" name="platform/external/scrypt" path="external/scrypt" revision="0306c7856fa4889c859ad6f4e56657afc553bf04"/> - <project groups="pdk" name="platform/external/sepolicy" path="external/sepolicy" revision="0be02b360fa94836d9ebdbd59790f7b3fcde950b"/> - <project groups="pdk-cw-fs,qcom_msm8x26" name="platform/external/sfntly" path="external/sfntly" revision="b75096eec64a4fed4940b626225ce94abc9bfc45"/> - <project groups="pdk-cw-fs,qcom_msm8x26" name="platform/external/skia" path="external/skia" revision="9bc988dadc2fb0a129e085882a09e8a370cba680"/> - <project groups="pdk-cw-fs" name="platform/external/smack" path="external/smack" revision="d7955ce24d294fb2014c59d11fca184471056f44"/> - <project groups="pdk-cw-fs" name="platform/external/smali" path="external/smali" revision="5fd395796e215a80c722815bf180728948868f18"/> - <project groups="pdk" name="platform/external/sonivox" path="external/sonivox" revision="399080e8ae3ebee97a5a57f1072452c4c77b5c5a"/> - <project groups="pdk" name="platform/external/speex" path="external/speex" revision="ff03110e77ec7fe716c5be11783746f59c814e30"/> - <project groups="pdk" name="platform/external/sqlite" path="external/sqlite" revision="a561e9ca8cdfd3c6a7cea00661f486f0b3394f43"/> - <project groups="pdk-cw-fs" name="platform/external/srec" path="external/srec" revision="c725e6c0486df74ad323f5c580e6dedceaf47740"/> - <project groups="pdk-cw-fs" name="platform/external/srtp" path="external/srtp" revision="cd2c0b6ce2e39a9ab13c802c5b8dfeb1ab0d1db5"/> - <project groups="pdk" name="platform/external/stlport" path="external/stlport" revision="db17bb0732fea4e8fe575f49045449e5b683fd7a"/> - <project groups="pdk-cw-fs" name="platform/external/strace" path="external/strace" revision="20ddb3d8dd2d4315dc33835ca73a99598159df01"/> - <project groups="pdk-cw-fs" name="platform/external/svox" path="external/svox" revision="6f30c2a64dc0a1d22fe3e9d65b963a2f6cf85f46"/> - <project groups="pdk-cw-fs,tradefed" name="platform/external/tagsoup" path="external/tagsoup" revision="a97828cb3f8f3a1af8470e55d3c5cd62d6a7cb4c"/> - <project groups="pdk,pdk-cw-fs" name="platform/external/tcpdump" path="external/tcpdump" revision="de49cdcfddf36f2b41ef3278e98a8a550a189952"/> - <project groups="pdk-cw-fs" name="platform/external/timezonepicker-support" path="external/timezonepicker-support" revision="99e91a76fd74bad10266623d67cdb98d011f709e"/> - <project groups="pdk" name="platform/external/tinyalsa" path="external/tinyalsa" revision="8863816dc5659a1e4678d17906c90844264d1588"/> - <project groups="pdk" name="platform/external/tinycompress" path="external/tinycompress" revision="25a4b4b5c7451702a164c98ef502e41cc03e1e1f"/> - <project groups="pdk" name="platform/external/tinyxml" path="external/tinyxml" revision="143125ff631c481d590cae0d7cc9ccfaaca269c7"/> - <project groups="pdk" name="platform/external/tinyxml2" path="external/tinyxml2" revision="7974ba13a557b3352b0fd4b2a8c377cb530e886e"/> - <project groups="pdk" name="platform/external/toybox" path="external/toybox" revision="7fcfbe7a2e99fe96e68ffe8d87370b86097d3999"/> - <project groups="pdk" name="platform/external/tremolo" path="external/tremolo" revision="8335d8b2ef4d22dcaccda9726c3a1460be2bd86c"/> - <project groups="pdk" name="platform/external/valgrind" path="external/valgrind" revision="085e341dfce074fad86c3b4bedb7d4da5d4413ae"/> - <project groups="pdk" name="platform/external/vixl" path="external/vixl" revision="4a06316541258e3c058792321295ee36d409f419"/> - <project groups="pdk" name="platform/external/vogar" path="external/vogar" revision="5a8fd4b1d6c046471c7b951680cace3eec723fe7"/> - <project groups="pdk-cw-fs,qcom_msm8x26" name="platform/external/webp" path="external/webp" revision="af51b94a435132e9014c324e25fb686b3d07a8c8"/> - <project groups="pdk" name="platform/external/webrtc" path="external/webrtc" revision="a8b6bbfff655d53ed7b1ce794708123c296e21cc"/> - <project groups="pdk" name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="907fe1cb0a32f78039e3a4ebe0c4b161da120061"/> - <project groups="pdk-cw-fs" name="platform/external/xmlwriter" path="external/xmlwriter" revision="e95d92246ee35273dde2bee8b00485cc14c12be5"/> - <project groups="pdk-cw-fs" name="platform/external/xmp_toolkit" path="external/xmp_toolkit" revision="42ea4dc6d1fc2206a7778029070ed9213e3b0fbf"/> - <project groups="pdk" name="platform/external/yaffs2" path="external/yaffs2" revision="8a536528cfe064314dc8afdc0eec0d62adffdab9"/> - <project groups="pdk" name="platform/external/zlib" path="external/zlib" revision="f42217451397d7637b46f8478a5e77df3083baaa"/> - <project groups="pdk-cw-fs" name="platform/external/zopfli" path="external/zopfli" revision="bb96afe13a50bfc17259dcf56f44e997923c705c"/> - <project groups="pdk-cw-fs" name="platform/external/zxing" path="external/zxing" revision="2b56cc1c1442ba598ed1ee9c23e8e9eade076e77"/> - <project groups="pdk" name="platform/frameworks/av" path="frameworks/av" revision="b0eb7b0a4c1c8f437d099eb14007863a94fcfbf0"/> - <project groups="pdk-cw-fs" name="platform/frameworks/base" path="frameworks/base" revision="abdaa32dd79c915d0e419560c8eaa64e3d946b77"/> - <project groups="pdk" name="platform/frameworks/compile/libbcc" path="frameworks/compile/libbcc" revision="b14e86905e0ffbee1d2b80abe87f6616e6831bae"/> - <project groups="pdk" name="platform/frameworks/compile/mclinker" path="frameworks/compile/mclinker" revision="dfd6c08c66b4b3d58fd28b5376478381e1a5647a"/> - <project groups="pdk" name="platform/frameworks/compile/slang" path="frameworks/compile/slang" revision="c4ada7adfa668950a1189832017f7f2469a28d7b"/> - <project groups="pdk-cw-fs" name="platform/frameworks/ex" path="frameworks/ex" revision="842e82f6b8d85c71469f4decdfd5d1a486d55881"/> - <project groups="pdk-cw-fs" name="platform/frameworks/mff" path="frameworks/mff" revision="b9669b8540a1e5c953374d53b115514335e23c27"/> - <project groups="pdk-cw-fs" name="platform/frameworks/minikin" path="frameworks/minikin" revision="69d4fba2f2b7bb2c248cc0e78cf277a6e44665f8"/> - <project groups="pdk-cw-fs" name="platform/frameworks/ml" path="frameworks/ml" revision="21053fad6555b9e0063e263c729aae9beeae7e2b"/> - <project groups="pdk-cw-fs" name="platform/frameworks/multidex" path="frameworks/multidex" revision="8c2abf7f471b061b737e700af711e9d5d6883b40"/> - <project groups="pdk" name="platform/frameworks/native" path="frameworks/native" revision="f8954c81a4ec43958867d1f6f497ef449bf091fd"/> - <project name="platform/frameworks/opt/bitmap" path="frameworks/opt/bitmap" revision="5c102db5a1a16a2adcc7728693a6e65a981f91ae"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/bluetooth" path="frameworks/opt/bluetooth" revision="192d793d2586b620027edd5b45ff4c72a86cc7be"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/calendar" path="frameworks/opt/calendar" revision="03b18577f8f8f799e87a62b8e03889ddacf6daa2"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/carddav" path="frameworks/opt/carddav" revision="f08aa2df132dd8dc32a0013d3750137d9dd9280a"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/chips" path="frameworks/opt/chips" revision="43f14897cf4577ee319d4a53c0410fe2755735f4"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/colorpicker" path="frameworks/opt/colorpicker" revision="f22a676aa67d7913d3436e395fdb7e24e17bb3f8"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/datetimepicker" path="frameworks/opt/datetimepicker" revision="bf572fc2476eb041d281a0722e23fd00d6a15922"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="709f713ebcd62c61defc270d945810efca179621"/> - <project name="platform/frameworks/opt/inputconnectioncommon" path="frameworks/opt/inputconnectioncommon" revision="3baece9b20fa480da46d860acd7320fd9eee3386"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/inputmethodcommon" path="frameworks/opt/inputmethodcommon" revision="990fcb1a6dbb5d1204cc8ec86e4bc3f691f4aeeb"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/mms" path="frameworks/opt/mms" revision="4a5bba9cfefb96706390307b7cf06271b7f9f5e2"/> - <project name="platform/frameworks/opt/net/ethernet" path="frameworks/opt/net/ethernet" revision="74d270d167ed6c3a6fa28e426da80d51a44a2af0"/> - <project groups="frameworks_ims,pdk-cw-fs" name="platform/frameworks/opt/net/ims" path="frameworks/opt/net/ims" revision="3ddaa6ec08d417d2848775ad3b5b01b865a9c891"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/net/voip" path="frameworks/opt/net/voip" revision="cf38b8464007ebf626fc0d61a646491fc3d794cd"/> - <project groups="pdk" name="platform/frameworks/opt/net/wifi" path="frameworks/opt/net/wifi" revision="cd84f31168f7d3cac6d548aa295a479cc693b89b"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/photoviewer" path="frameworks/opt/photoviewer" revision="05b4a96fd6fc0f6bc8b56950fa40102b87a747ee"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/setupwizard" path="frameworks/opt/setupwizard" revision="5e1533ae4d68022e854e3d89dd67454820c46526"/> - <project groups="pdk" name="platform/frameworks/opt/telephony" path="frameworks/opt/telephony" revision="2865ee97881486cc533e0336b9865ca5a6ee0a2a"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/timezonepicker" path="frameworks/opt/timezonepicker" revision="a508e1f3dd3cc76b98020d319d95878737802cc3"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/vcard" path="frameworks/opt/vcard" revision="210ebaab315e389ffc66278e28ecd6230e412b5f"/> - <project groups="pdk-cw-fs" name="platform/frameworks/opt/widget" path="frameworks/opt/widget" revision="466e0e0307b3f6aa4f4be3d9419b5996bd389da5"/> - <project groups="pdk" name="platform/frameworks/rs" path="frameworks/rs" revision="5c9fcdab0f89b7cf18effdc3fd5becbac59d35e0"/> - <project groups="pdk-cw-fs" name="platform/frameworks/support" path="frameworks/support" revision="421d8baa4a524e1384bcf033360bccaf8d55081d"/> - <project groups="pdk-cw-fs" name="platform/frameworks/testing" path="frameworks/testing" revision="f9b3351f18ae617ea4debddce931a9381ab76a4c"/> - <project groups="pdk-cw-fs" name="platform/frameworks/volley" path="frameworks/volley" revision="008e0cc8e51ef9e91110d91d4d662d0d86b252a1"/> - <project groups="pdk-cw-fs" name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="bdbcdf52bb5aa9fbd20d2e2d7877eb6549962c89"/> - <project name="platform/hardware/akm" path="hardware/akm" revision="068a97a299a8e0d837b8ac67635a96b59595c582"/> - <project groups="pdk" name="platform/hardware/broadcom/libbt" path="hardware/broadcom/libbt" revision="6a45b5611fa101770c6641ddda1aa83fe47b74be"/> - <project groups="broadcom_wlan" name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="350074487acb6e5b75cf3149ebe815e060e60394"/> - <project groups="intel" name="platform/hardware/intel/audio_media" path="hardware/intel/audio_media" revision="0ce92df294da2b05fd06c7da49ac5324e68c7a14"/> - <project groups="intel" name="platform/hardware/intel/bootstub" path="hardware/intel/bootstub" revision="f35042d850c2a056c937a1140a6462dd6411279b"/> - <project groups="intel" name="platform/hardware/intel/common/bd_prov" path="hardware/intel/common/bd_prov" revision="8af329f2d2b54dfcfa84051d3ce1fae95f79011a"/> - <project groups="intel" name="platform/hardware/intel/common/libmix" path="hardware/intel/common/libmix" revision="a0b150db4d1ed2bf5234eeec36a4dd2a88ec6b53"/> - <project groups="intel" name="platform/hardware/intel/common/libstagefrighthw" path="hardware/intel/common/libstagefrighthw" revision="419d34016dceec65ea137490668984eb80119df4"/> - <project groups="intel" name="platform/hardware/intel/common/libva" path="hardware/intel/common/libva" revision="afa22e4e541f3641f5525350b760f5037b452b33"/> - <project groups="intel" name="platform/hardware/intel/common/libwsbm" path="hardware/intel/common/libwsbm" revision="77bfea2e6a3dc1e30a17780b48b7b231eef77255"/> - <project groups="intel" name="platform/hardware/intel/common/omx-components" path="hardware/intel/common/omx-components" revision="5da72011e0c14cf41ac9a2b3f93e59ff7b8be219"/> - <project groups="intel" name="platform/hardware/intel/common/utils" path="hardware/intel/common/utils" revision="9d7a792711ec5e4fb3474ceff21bdd14547d0981"/> - <project groups="intel" name="platform/hardware/intel/common/wrs_omxil_core" path="hardware/intel/common/wrs_omxil_core" revision="3f7ceee13aa17ae32d4263aed2ce67eb9a37c58b"/> - <project groups="intel" name="platform/hardware/intel/img/hwcomposer" path="hardware/intel/img/hwcomposer" revision="c7d7763e1230229aa2c82b53252f752b1f83aab0"/> - <project groups="intel" name="platform/hardware/intel/img/libdrm" path="hardware/intel/img/libdrm" revision="20e32a079154bb3a36ccb43a4dd8e25bd1ef01de"/> - <project groups="intel" name="platform/hardware/intel/img/psb_headers" path="hardware/intel/img/psb_headers" revision="58ab4ceb5ea3d2733f108cacfcccb93e0c8d84da"/> - <project groups="intel" name="platform/hardware/intel/img/psb_video" path="hardware/intel/img/psb_video" revision="b35344f5c0b8568df0630efe9fce076e810de8d3"/> - <project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="5acdfec69b469d98e582e943effd806bd0298993"/> - <project groups="pdk" name="platform/hardware/libhardware" path="hardware/libhardware" revision="32fb8b2d9f8399a745a26dddc031cc16867ada2d"/> - <project groups="pdk" name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="62e06c838de988286d5d4ddd1d8a30f8af980139"/> - <project groups="nvidia_audio" name="platform/hardware/nvidia/audio" path="hardware/nvidia/audio" revision="3134b055c05e3681c1f71eed23bd0bd8e57ddfa7"/> - <project groups="tegra124" name="platform/hardware/nvidia/tegra124" path="hardware/nvidia/tegra124" revision="77d1e2a4bb07d97a7f140f0fa8ddb8b6d52327f6"/> - <project groups="qcom,qcom_audio" name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="bf93daed8583c0f2deec915c6f55064845f905e4"/> - <project groups="qcom" name="platform/hardware/qcom/bt" path="hardware/qcom/bt" revision="d2b071c3683bace40c9ed666107367dac5a5bb45"/> - <project groups="qcom,qcom_display" name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="44c848f8fd5bc279d2579df5548e5051a325b729"/> - <project groups="qcom,qcom_gps" name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="e5949fd1375692f23d2abd3bae1615ec68df2311"/> - <project groups="qcom" name="platform/hardware/qcom/keymaster" path="hardware/qcom/keymaster" revision="e8d59957d4935fb737ee3604d21b34fa3afb7e95"/> - <project groups="qcom" name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="1147997cdb1be4218fc9f346d02e236683fbde1f"/> - <project groups="qcom_msm8960" name="platform/hardware/qcom/msm8960" path="hardware/qcom/msm8960" revision="c25a431842a26b5756b58a9d4a42c776e0457ba2"/> - <project groups="qcom_msm8x26" name="platform/hardware/qcom/msm8x26" path="hardware/qcom/msm8x26" revision="0a928ed09e97d7aa2da93f221140be942d70266c"/> - <project groups="qcom_msm8x27" name="platform/hardware/qcom/msm8x27" path="hardware/qcom/msm8x27" revision="8ff5c0057cbdecfa09410c1710ba043e191a2862"/> - <project groups="qcom_msm8x74" name="platform/hardware/qcom/msm8x74" path="hardware/qcom/msm8x74" revision="39122a9905ea437593ad4f5171683bcaafad156f"/> - <project groups="qcom_msm8x84" name="platform/hardware/qcom/msm8x84" path="hardware/qcom/msm8x84" revision="3be8c1e260bcccc7d97043df623208b0531db364"/> - <project groups="qcom" name="platform/hardware/qcom/power" path="hardware/qcom/power" revision="ff9f4538c09399030fa73e3e65a167852cb91e8f"/> - <project groups="qcom" name="platform/hardware/qcom/sensors" path="hardware/qcom/sensors" revision="07c5bcdb36158e22d33bac02eecd83d4ff1fb2f8"/> - <project groups="qcom_wlan" name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="91840a20fc7e54c2aa2393b982a0abc85baa8299"/> - <project groups="pdk" name="platform/hardware/ril" path="hardware/ril" revision="f34ed01f1e1935c67e153916ea27dddae4d067dc"/> - <project groups="exynos5" name="platform/hardware/samsung_slsi/exynos5" path="hardware/samsung_slsi/exynos5" revision="2be288ff70a54d330c12496958a42b6d9e52b51e"/> - <project groups="omap3" name="platform/hardware/ti/omap3" path="hardware/ti/omap3" revision="40292fb9eeb2cf0bb95dc818da12ddcae40b931c"/> - <project groups="omap4-aah" name="platform/hardware/ti/omap4-aah" path="hardware/ti/omap4-aah" revision="ce711bd57caf8e9d06941d00cc75e216bb24fd9b"/> - <project groups="omap4" name="platform/hardware/ti/omap4xxx" path="hardware/ti/omap4xxx" revision="fe94a195639921ae99e5a286a735b2deb18b4a09"/> - <project groups="pdk" name="platform/libcore" path="libcore" revision="72f2e9119d04e7976e09d97c2779ccbddc6fffd8"/> - <project groups="pdk" name="platform/libnativehelper" path="libnativehelper" revision="c2fadae1a518c1eb92c4d1910fba9809e45caf40"/> - <project name="platform/ndk" path="ndk" revision="e505b304e02af3423a69735bb86fd1288a3641b4"/> - <project name="platform/packages/apps/BasicSmsReceiver" path="packages/apps/BasicSmsReceiver" revision="533f8542a278c967faa8ab6f6a3ff6c92f3675ba"/> - <project groups="pdk-cw-fs" name="platform/packages/apps/Bluetooth" path="packages/apps/Bluetooth" revision="37baf3fb0f7288738e137cfafd2b1353100ee76b"/> - <project name="platform/packages/apps/Browser" path="packages/apps/Browser" revision="fe15d2a0bf7b10a21a53a4e286f6bad5ccbce7d3"/> - <project name="platform/packages/apps/Calculator" path="packages/apps/Calculator" revision="2d4b45870ca51ea75e2ed4389d32a5f9f4ed1e7f"/> - <project name="platform/packages/apps/Calendar" path="packages/apps/Calendar" revision="0e7850d774e0c9f8a0f26d180bcdba25be95ea51"/> - <project name="platform/packages/apps/Camera" path="packages/apps/Camera" revision="618cae955e32fd4d7ede9a3e979e68ca8d663f15"/> - <project name="platform/packages/apps/Camera2" path="packages/apps/Camera2" revision="6871a7eaf8695f70bb39d7bd78c66b1dcffa6459"/> - <project name="platform/packages/apps/CellBroadcastReceiver" path="packages/apps/CellBroadcastReceiver" revision="3d4e27c6320bef3e0309b4fb170ad3f98b70664f"/> - <project groups="pdk-cw-fs" name="platform/packages/apps/CertInstaller" path="packages/apps/CertInstaller" revision="b23c2e03c27561369a98633c82227ee3a6014197"/> - <project name="platform/packages/apps/Contacts" path="packages/apps/Contacts" revision="553e03f650040e820642ccfcb90012c48fd2eb95"/> - <project name="platform/packages/apps/ContactsCommon" path="packages/apps/ContactsCommon" revision="a4419f35a372701f4ab75d9c834572ab506ebf04"/> - <project name="platform/packages/apps/DeskClock" path="packages/apps/DeskClock" revision="f83a53475a304b59b38df8e7012e173b32203c10"/> - <project name="platform/packages/apps/Dialer" path="packages/apps/Dialer" revision="68b0ee54c1f77b9884c100ad6b21887b1b9d37e8"/> - <project name="platform/packages/apps/Email" path="packages/apps/Email" revision="f44b729bff619d0a9f0b1492726351e41c1e5d5d"/> - <project name="platform/packages/apps/Exchange" path="packages/apps/Exchange" revision="7766cd438bf2ec7aa113b9d9e1a35fa94926ea54"/> - <project name="platform/packages/apps/Gallery" path="packages/apps/Gallery" revision="382ba169ac7e66201426399cc5f22bcaf3db01b9"/> - <project name="platform/packages/apps/Gallery2" path="packages/apps/Gallery2" revision="428ec9306e6a4b0edc540145a8f41c62dc329536"/> - <project name="platform/packages/apps/HTMLViewer" path="packages/apps/HTMLViewer" revision="2e368f6d87eb82691f855e93f85599b75b489731"/> - <project name="platform/packages/apps/InCallUI" path="packages/apps/InCallUI" revision="fc0d3f82a3efdd6b4a077e77ef5a245431588a50"/> - <project name="platform/packages/apps/KeyChain" path="packages/apps/KeyChain" revision="dfeaab7419362fd0dd0aaaa1b123323947f7be36"/> - <project name="platform/packages/apps/Launcher2" path="packages/apps/Launcher2" revision="b104036cf561bfb9b03ea5c98de469a2259aeeeb"/> - <project name="platform/packages/apps/Launcher3" path="packages/apps/Launcher3" revision="3e4c4987309b8cf76f524396738bfd75dd137498"/> - <project name="platform/packages/apps/LegacyCamera" path="packages/apps/LegacyCamera" revision="e48f33822a29d0cf0d72b68eb53e9662790e3fdb"/> - <project name="platform/packages/apps/ManagedProvisioning" path="packages/apps/ManagedProvisioning" revision="28491c19e41748407b9354d097bc0791896d5abe"/> - <project name="platform/packages/apps/Mms" path="packages/apps/Mms" revision="466cb5674614407596c332308b4119decaa22aad"/> - <project name="platform/packages/apps/Music" path="packages/apps/Music" revision="2d11727e5ecf15880dd09295846e189f4e85d656"/> - <project name="platform/packages/apps/MusicFX" path="packages/apps/MusicFX" revision="c2a07ce075e18f802dddc5f47f41818a1be318a7"/> - <project name="platform/packages/apps/Nfc" path="packages/apps/Nfc" revision="28e527fc19ec0354c641174087fcdd6a32b15415"/> - <project name="platform/packages/apps/OneTimeInitializer" path="packages/apps/OneTimeInitializer" revision="01e429c08e51291315890de9677151a7e0b6ad35"/> - <project name="platform/packages/apps/PackageInstaller" path="packages/apps/PackageInstaller" revision="592868a52673dc7a3255447fb43d8d8572f791ff"/> - <project name="platform/packages/apps/Phone" path="packages/apps/Phone" revision="79731f02b7009206a01182d2cca15dfc8491da09"/> - <project name="platform/packages/apps/PhoneCommon" path="packages/apps/PhoneCommon" revision="a34883557d27662e7d6ed98035f90335d0c09cf5"/> - <project name="platform/packages/apps/Protips" path="packages/apps/Protips" revision="9b6836aabee945b6c7a54796a4e6a7ae735f423c"/> - <project name="platform/packages/apps/Provision" path="packages/apps/Provision" revision="78ca0db658fe6253d506916e36319e620476f809"/> - <project name="platform/packages/apps/QuickSearchBox" path="packages/apps/QuickSearchBox" revision="2061b9fa4011d75b2558fdae0eec7cfc9c8eefc6"/> - <project name="platform/packages/apps/Settings" path="packages/apps/Settings" revision="e6af93277c5c5fe9c76af59a4b1d523143f2da93"/> - <project name="platform/packages/apps/SmartCardService" path="packages/apps/SmartCardService" revision="29eae320a4bd222b5ff1c092f84f1aebba88d0b7"/> - <project name="platform/packages/apps/SoundRecorder" path="packages/apps/SoundRecorder" revision="c9fcd85287878c7b58b84a69353526facae28af2"/> - <project name="platform/packages/apps/SpareParts" path="packages/apps/SpareParts" revision="4db997871e3f4c3f84660815096e5276b47c5c91"/> - <project name="platform/packages/apps/SpeechRecorder" path="packages/apps/SpeechRecorder" revision="536aa74ff3a77186bef29dc9333a34688fa59d13"/> - <project name="platform/packages/apps/Stk" path="packages/apps/Stk" revision="f85c76f009148c932a27c86e975da5c59e64e9e2"/> - <project name="platform/packages/apps/Tag" path="packages/apps/Tag" revision="d9411064719902245bf6251ce39a3fa841ee35c7"/> - <project name="platform/packages/apps/TvSettings" path="packages/apps/TvSettings" revision="03a27b810ce70f2496f00a59ec79feb1da4e3b64"/> - <project name="platform/packages/apps/UnifiedEmail" path="packages/apps/UnifiedEmail" revision="e6784ccfb4882430073352d42179765add59412f"/> - <project name="platform/packages/apps/VoiceDialer" path="packages/apps/VoiceDialer" revision="fd726afabfb115a17c1b4dca8d2129ca3501f1f9"/> - <project name="platform/packages/experimental" path="packages/experimental" revision="72836101d3ec4ad9f16b354c47f8ed8451fb9b99"/> - <project name="platform/packages/inputmethods/LatinIME" path="packages/inputmethods/LatinIME" revision="19eefc5109b65b1ecf74190904a1c1aa3b30b640"/> - <project name="platform/packages/inputmethods/OpenWnn" path="packages/inputmethods/OpenWnn" revision="59aefa242169b7a51c2381daee58ff22fd1834ce"/> - <project name="platform/packages/providers/ApplicationsProvider" path="packages/providers/ApplicationsProvider" revision="8268a4c790c65bd281ccddc05d272594e4194431"/> - <project groups="pdk-cw-fs" name="platform/packages/providers/CalendarProvider" path="packages/providers/CalendarProvider" revision="a0960e75e946c6412452e6c91ac0d22933c00fd5"/> - <project groups="pdk-cw-fs" name="platform/packages/providers/ContactsProvider" path="packages/providers/ContactsProvider" revision="91f091ffdbd4a87f02cdaedaf61344392d1f5e40"/> - <project groups="pdk-cw-fs" name="platform/packages/providers/DownloadProvider" path="packages/providers/DownloadProvider" revision="b4353615031e181b666417848f9e7a4283a6265a"/> - <project groups="pdk-cw-fs" name="platform/packages/providers/MediaProvider" path="packages/providers/MediaProvider" revision="1646ab9f8650d341af3e976a1afead8b79365bdc"/> - <project name="platform/packages/providers/PartnerBookmarksProvider" path="packages/providers/PartnerBookmarksProvider" revision="96d0a80af45923767baf449fc8c735c2f71d64ae"/> - <project name="platform/packages/providers/TelephonyProvider" path="packages/providers/TelephonyProvider" revision="dd36f149b5574211136780885459e94c515cec54"/> - <project name="platform/packages/providers/TvProvider" path="packages/providers/TvProvider" revision="5462b213ed14735289692cf525a46aa27fc3ba26"/> - <project groups="pdk-cw-fs" name="platform/packages/providers/UserDictionaryProvider" path="packages/providers/UserDictionaryProvider" revision="fffeca3719057b8de24aedd6007fca162c027be5"/> - <project name="platform/packages/screensavers/Basic" path="packages/screensavers/Basic" revision="1525543c2d8f5c7e55de68d15c1e138d3f3bbb2a"/> - <project name="platform/packages/screensavers/PhotoTable" path="packages/screensavers/PhotoTable" revision="619158b68f68e627cc770158fe92873c045204a9"/> - <project name="platform/packages/screensavers/WebView" path="packages/screensavers/WebView" revision="6e0a80f6faed6191acc8ce1b6c79eada09e9e042"/> - <project name="platform/packages/services/Mms" path="packages/services/Mms" revision="ae4babc2b2ed3031dd7a848bab0c2961ec93efb8"/> - <project name="platform/packages/services/Telecomm" path="packages/services/Telecomm" revision="88d44c3fdb01d714c361aca74ba9724c555c651f"/> - <project name="platform/packages/services/Telephony" path="packages/services/Telephony" revision="6e24805f6e1139e98c73e255fa36afc33e640525"/> - <project name="platform/packages/wallpapers/Basic" path="packages/wallpapers/Basic" revision="65a0d4bf3e95bc35c284dd7a4b2b6634c9032e0c"/> - <project name="platform/packages/wallpapers/Galaxy4" path="packages/wallpapers/Galaxy4" revision="23b377b33e19186281770009e688247873b2cbc6"/> - <project name="platform/packages/wallpapers/HoloSpiral" path="packages/wallpapers/HoloSpiral" revision="d8f32caf891a089946bc9c0d1bdb8d04a12103f7"/> - <project name="platform/packages/wallpapers/LivePicker" path="packages/wallpapers/LivePicker" revision="e0029b91ba0c3e5e5bc355cdaaa7a8c5e9301546"/> - <project name="platform/packages/wallpapers/MagicSmoke" path="packages/wallpapers/MagicSmoke" revision="49550635fa42e1728eaf5968f2b3cc6363354be9"/> - <project name="platform/packages/wallpapers/MusicVisualization" path="packages/wallpapers/MusicVisualization" revision="2d55c82db6459c0ac8cffd9a0a279eb576c9b074"/> - <project name="platform/packages/wallpapers/NoiseField" path="packages/wallpapers/NoiseField" revision="97c177471e95bda94b3409afb0f8d105c432866a"/> - <project name="platform/packages/wallpapers/PhaseBeam" path="packages/wallpapers/PhaseBeam" revision="5cf62b2505f54247bd5aed0ec6c13101f267af3a"/> - <project groups="pdk" name="platform/pdk" path="pdk" revision="d1ce657ea1560272a08e2090ef241301ea012447"/> - <project name="platform/prebuilts/android-emulator" path="prebuilts/android-emulator" revision="f5124fada24f678bc88a498a2b3d36487b216180"/> - <project groups="pdk,darwin" name="platform/prebuilts/clang/darwin-x86/3.1" path="prebuilts/clang/darwin-x86/3.1" revision="426233405bef3c7c825095ab14256c3773894b9b"/> - <project groups="pdk,darwin" name="platform/prebuilts/clang/darwin-x86/3.2" path="prebuilts/clang/darwin-x86/3.2" revision="af856d77b3cbb1f6afccdc531bee991403c28907"/> - <project groups="arm,darwin,pdk-cw-fs" name="platform/prebuilts/clang/darwin-x86/arm/3.3" path="prebuilts/clang/darwin-x86/arm/3.3" revision="54acc51e28850485e380b55916868a4e1ff17998"/> - <project groups="pdk,darwin" name="platform/prebuilts/clang/darwin-x86/host/3.4" path="prebuilts/clang/darwin-x86/host/3.4" revision="a798fe00dbd92ad4e5f7123a2e2bc1d805db04f6"/> - <project groups="pdk,darwin" name="platform/prebuilts/clang/darwin-x86/host/3.5" path="prebuilts/clang/darwin-x86/host/3.5" revision="0b2b09cc30ef2f1c9a8eed21da0fa92811c4974c"/> - <project name="platform/prebuilts/clang/darwin-x86/host/3.6" path="prebuilts/clang/darwin-x86/host/3.6" revision="ac78ef93d9733ab46adf7ec46f7730e941c476a0"/> - <project groups="darwin,mips,pdk-cw-fs" name="platform/prebuilts/clang/darwin-x86/mips/3.3" path="prebuilts/clang/darwin-x86/mips/3.3" revision="da3dad928542362835082b2eda44e4dc315d65bb"/> - <project groups="darwin,pdk-cw-fs,x86" name="platform/prebuilts/clang/darwin-x86/x86/3.3" path="prebuilts/clang/darwin-x86/x86/3.3" revision="f67a83f35e30f92b312fbee852184c3f6dc38f34"/> - <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/> - <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/> - <project groups="arm,linux,pdk-cw-fs" name="platform/prebuilts/clang/linux-x86/arm/3.3" path="prebuilts/clang/linux-x86/arm/3.3" revision="2f6d2db9e2af3507d132cf5d286a42fe1d47f7bc"/> - <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.4" path="prebuilts/clang/linux-x86/host/3.4" revision="fae26a039f79d780ddedcad07f164d9e6c05fc87"/> - <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="bb02bdf737ba8511177e2aee1f722e0ce5f14f2e"/> - <project name="platform/prebuilts/clang/linux-x86/host/3.6" path="prebuilts/clang/linux-x86/host/3.6" revision="729e83120144d159c3c0ceaf6d189f6a088b3dac"/> - <project groups="linux,mips,pdk-cw-fs" name="platform/prebuilts/clang/linux-x86/mips/3.3" path="prebuilts/clang/linux-x86/mips/3.3" revision="51f8e2760628588fe268438d612d942c30d13fb2"/> - <project groups="linux,pdk-cw-fs,x86" name="platform/prebuilts/clang/linux-x86/x86/3.3" path="prebuilts/clang/linux-x86/x86/3.3" revision="017a8a67f92a66b29ab17772e50642a7b9d0f8e6"/> - <project name="platform/prebuilts/devtools" path="prebuilts/devtools" revision="ea79f9831e9ff72ce4251010eebe5185d3c6c548"/> - <project groups="pdk" name="platform/prebuilts/eclipse" path="prebuilts/eclipse" revision="cf9f78f8cf41b16edf9f712598a42743d5cea4af"/> - <project groups="notdefault,eclipse" name="platform/prebuilts/eclipse-build-deps" path="prebuilts/eclipse-build-deps" revision="ceb739d6a7c10f5fb5a6cf6e1f702453b1361ad3"/> - <project groups="notdefault,eclipse" name="platform/prebuilts/eclipse-build-deps-sources" path="prebuilts/eclipse-build-deps-sources" revision="8b7d8f6033ffe2d22905d10cf6d57d5bdcbe519b"/> - <project groups="pdk,darwin,arm" name="platform/prebuilts/gcc/darwin-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/darwin-x86/aarch64/aarch64-linux-android-4.8" revision="a261d38eaebb7ff406a6bb60237b36fc61714d46"/> - <project groups="pdk,darwin,arm" name="platform/prebuilts/gcc/darwin-x86/aarch64/aarch64-linux-android-4.9" path="prebuilts/gcc/darwin-x86/aarch64/aarch64-linux-android-4.9" revision="4025543df464a3cb3572e3634a24278c707ee2df"/> - <project groups="pdk,darwin,arm" name="platform/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8" revision="6d08ca9f45ff685648fd13c75bf5cac4b11c19bb"/> - <project groups="pdk,darwin,arm" name="platform/prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.8" revision="264394c23b2686ce52cd4ffb116ced127aa7f8fc"/> - <project name="platform/prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9" path="prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9" revision="e65de21ec791d7c7dd812416fc5bb7865912a5ef"/> - <project groups="pdk,darwin" name="platform/prebuilts/gcc/darwin-x86/host/headers" path="prebuilts/gcc/darwin-x86/host/headers" revision="4ac4f7cc41cf3c9e36fc3d6cf37fd1cfa9587a68"/> - <project groups="pdk,darwin" name="platform/prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1" path="prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1" revision="8834958755acc291d126ba7ee38ac731d04f9c9e"/> - <project groups="pdk,darwin,mips" name="platform/prebuilts/gcc/darwin-x86/mips/mips64el-linux-android-4.8" path="prebuilts/gcc/darwin-x86/mips/mips64el-linux-android-4.8" revision="3b5bef47de8017ff39ef5bfbe801e3fa6b272fab"/> - <project groups="pdk,darwin,mips" name="platform/prebuilts/gcc/darwin-x86/mips/mips64el-linux-android-4.9" path="prebuilts/gcc/darwin-x86/mips/mips64el-linux-android-4.9" revision="b3e5128b2196ecf82b12363409f443f18eb46a9c"/> - <project groups="pdk,darwin,mips" name="platform/prebuilts/gcc/darwin-x86/mips/mipsel-linux-android-4.8" path="prebuilts/gcc/darwin-x86/mips/mipsel-linux-android-4.8" revision="ba97180acd4251d3acf08530faa4a724af74abd3"/> - <project groups="pdk,darwin,x86" name="platform/prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.8" revision="151333b6cf70c6fc075d18e28e4bb317a666dc8f"/> - <project groups="pdk,darwin,x86" name="platform/prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.9" path="prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.9" revision="8edfd4eb3d69ff37346bc3b3f8ea78462e4380c8"/> - <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="7334f0a7a872700d0aaf00bea75917c077c45530"/> - <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9" revision="6a20db030e486326e70968612662938d12d86a7b"/> - <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="26e93f6af47f7bd3a9beb5c102a5f45e19bfa38a"/> - <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="d9735fc81434f2af2c44d86ca57740c673c8d9bc"/> - <project name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" revision="acb2418543b4fc109c51e95acf566cb42f7a9912"/> - <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="fdd759c108d1ad27b9b6e134ee346c3b52d52125"/> - <project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8" revision="f61a459478cdc31e8aae22a182cdbf814ba08012"/> - <project name="platform/prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8" revision="f691cae2f256d5f72388c0ce9113007a53ad333a"/> - <project groups="pdk,linux,mips" name="platform/prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.8" path="prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.8" revision="38586de6b44714b4adcf21119fe6b267e33f3ca6"/> - <project groups="pdk,linux,mips" name="platform/prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.9" path="prebuilts/gcc/linux-x86/mips/mips64el-linux-android-4.9" revision="9de691053130c6d0d07774741aa551efbba13fa6"/> - <project groups="pdk,linux,mips" name="platform/prebuilts/gcc/linux-x86/mips/mipsel-linux-android-4.8" path="prebuilts/gcc/linux-x86/mips/mipsel-linux-android-4.8" revision="c06b9b305c365163c99d4ffba49ac37ce2716024"/> - <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="e239c938935058df515225b6224103078270aed8"/> - <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9" revision="469c65ad4eef1d43e79d8399e4e4282a00161ac5"/> - <project groups="pdk-cw-fs" name="platform/prebuilts/gradle-plugin" path="prebuilts/gradle-plugin" revision="c528a451023d3bf8c93d0d87f70d1b4127b729eb"/> - <project groups="pdk-cw-fs" name="platform/prebuilts/libs/libedit" path="prebuilts/libs/libedit" revision="d32685dba4011664b590b94ad156bc734c2c9bb5"/> - <project groups="pdk-cw-fs" name="platform/prebuilts/maven_repo/android" path="prebuilts/maven_repo/android" revision="12a24bf4124f5a9fb2f21950568502ef7f8a55e3"/> - <project groups="pdk,tradefed" name="platform/prebuilts/misc" path="prebuilts/misc" revision="f5f456d2745e7e68b8e2b90260fc06de7d30a596"/> - <project groups="pdk" name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="7714ae663f56992505cee31ddc8203f8c99da5a1"/> - <project groups="darwin,pdk,pdk-cw-fs" name="platform/prebuilts/python/darwin-x86/2.7.5" path="prebuilts/python/darwin-x86/2.7.5" revision="2bdd4fd418614c7c0101147d02199d0e47c4980e"/> - <project groups="linux,pdk,pdk-cw-fs" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="5de4f653a1cff7d7acbbb933711537ef47e2723c"/> - <project groups="pdk" name="platform/prebuilts/qemu-kernel" path="prebuilts/qemu-kernel" revision="1dffc580d656397f0ffca65820aac524a7ba6f77"/> - <project groups="pdk,tradefed" name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="aba340a0b47f3bf28e65b098ed03fb5c94441ed4"/> - <project groups="pdk,tools" name="platform/prebuilts/tools" path="prebuilts/tools" revision="f34d96a2e4035a9f7aa15d41ddff45b836c38785"/> - <project groups="pdk-cw-fs" name="platform/sdk" path="sdk" revision="6e909dbb16b137b08545df345c3fcffd262ffc7f"/> - <project groups="pdk" name="platform/system/core" path="system/core" revision="bc2602068d83b0226a614ed143cebd708c5fabd2"/> - <project groups="pdk" name="platform/system/extras" path="system/extras" revision="f511e6a2fa049753f64bd737a4d74ff0f88cc611"/> - <project groups="pdk" name="platform/system/keymaster" path="system/keymaster" revision="3809b939fb680031a53f6f5a1c157bba8dee5636"/> - <project groups="pdk" name="platform/system/media" path="system/media" revision="29a4e2837b89114cc4da1f991badf2656f342cb5"/> - <project groups="pdk" name="platform/system/netd" path="system/netd" revision="a0b06f61c55be2ecea35d14b621553c00bf287a6"/> - <project groups="pdk" name="platform/system/security" path="system/security" revision="3a6456ec88ad4a3dd4cf5620c328adef998be82d"/> - <project groups="pdk" name="platform/system/vold" path="system/vold" revision="89bcc638ab24af7bee0ff3ccfa190a08b721f0a4"/> - <project groups="notdefault,tools" name="platform/tools/adt/eclipse" path="tools/adt/eclipse" revision="ede2ed86419bb4c78428f1ac09825b1a247d8e24"/> - <project groups="notdefault,tools" name="platform/tools/adt/idea" path="tools/adt/idea" revision="e04d82f626ae5a54047bac38673994f374672f61"/> - <project groups="notdefault,tools" name="platform/tools/base" path="tools/base" revision="b17e827e542dbbe9891560b86e37729896a1e3ea"/> - <project groups="notdefault,tools" name="platform/tools/build" path="tools/build" revision="69c4b95102b4b9862bfba68b3eaf5b7537a705ee"/> - <project groups="notdefault,tools" name="platform/tools/emulator" path="tools/emulator" revision="c427e5d5227ba9413307670a5d758d9ced394a7e"/> - <project groups="tools" name="platform/tools/external/fat32lib" path="tools/external/fat32lib" revision="3880776e41ff7def06e351720f2d162f88b58a03"/> - <project groups="tools" name="platform/tools/external/gradle" path="tools/external/gradle" revision="ca6f02646b8ee0b57339cee983a6d5b3fa2e2ae6"/> - <project groups="notdefault,tools" name="platform/tools/idea" path="tools/idea" revision="9b5d02ac8c92b1e71523cc15cb3d168d57fbd898"/> - <project groups="notdefault,tradefed" name="platform/tools/loganalysis" path="tools/loganalysis" revision="e64f495107aaa91f2e40e7e5c92c700d58115fa3"/> - <project groups="notdefault,motodev" name="platform/tools/motodev" path="tools/motodev" revision="69989786cefbde82527960a1e100ec9afba46a98"/> - <project groups="notdefault,tools" name="platform/tools/studio/cloud" path="tools/studio/cloud" revision="58f06e77e051fff3903adabca7acdaa9dd12ec2d"/> - <project groups="notdefault,tools" name="platform/tools/studio/translation" path="tools/studio/translation" revision="4e094acd23094d6edf9823167adf683d2a327de2"/> - <project groups="notdefault,tools" name="platform/tools/swt" path="tools/swt" revision="823d8a00c6d466dec870d791643766d3b8fbd08d"/> -</manifest>
diff --git a/android_webview/buildbot/deps_whitelist.py b/android_webview/buildbot/deps_whitelist.py deleted file mode 100755 index 398148f..0000000 --- a/android_webview/buildbot/deps_whitelist.py +++ /dev/null
@@ -1,251 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# -"""Logic to generate lists of DEPS used by various parts of -the android_webview continuous integration (buildbot) infrastructure. - -Note: The root Chromium project (which is not explicitly listed here) -has a couple of third_party libraries checked in directly into it. This means -that the list of third parties present in this file is not a comprehensive -list of third party android_webview dependencies. -""" - -import argparse -import json -import logging -import os -import sys - -# Add android_webview/tools to path to get at known_issues. -sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'tools')) -import known_issues - - -class DepsWhitelist(object): - def __init__(self): - # If a new DEPS entry is needed for the AOSP bot to compile please add it - # here first. - # This is a staging area for deps that are accepted by the android_webview - # team and are in the process of having the required branches being created - # in the Android tree. - self._compile_but_not_snapshot_dependencies = [ - ] - - # Dependencies that need to be merged into the Android tree. - self._snapshot_into_android_dependencies = [ - 'sdch/open-vcdiff', - 'testing/gtest', - 'third_party/WebKit', - 'third_party/angle', - 'third_party/boringssl/src', - 'third_party/brotli/src', - ('third_party/eyesfree/src/android/java/src/com/googlecode/eyesfree/' - 'braille'), - 'third_party/freetype', - 'third_party/icu', - 'third_party/leveldatabase/src', - 'third_party/libaddressinput/src', - 'third_party/libjingle/source/talk', - 'third_party/libjpeg_turbo', - 'third_party/libphonenumber/src/phonenumbers', - 'third_party/libphonenumber/src/resources', - 'third_party/libsrtp', - 'third_party/libvpx', - 'third_party/libyuv', - 'third_party/mesa/src', - 'third_party/openmax_dl', - 'third_party/opus/src', - 'third_party/ots', - 'third_party/sfntly/cpp/src', - 'third_party/skia', - 'third_party/smhasher/src', - 'third_party/snappy/src', - 'third_party/usrsctp/usrsctplib', - 'third_party/webrtc', - 'third_party/yasm/source/patched-yasm', - 'tools/grit', - 'tools/gyp', - 'v8', - ] - - # We can save some time by not rsyncing code we don't use. - self._prune_from_rsync_build = [ - 'third_party/WebKit/LayoutTests', - ] - - # Dependencies required to build android_webview. - self._compile_dependencies = (self._snapshot_into_android_dependencies + - self._compile_but_not_snapshot_dependencies) - - # Dependencies required to run android_webview tests but not required to - # compile. - self._test_data_dependencies = [ - 'chrome/test/data/perf/third_party/octane', - ] - - @staticmethod - def _read_deps_file(deps_file_path): - class FileImplStub(object): - """Stub for the File syntax.""" - def __init__(self, file_location): - pass - - @staticmethod - def GetPath(): - return '' - - @staticmethod - def GetFilename(): - return '' - - @staticmethod - def GetRevision(): - return None - - def from_stub(__, _=None): - """Stub for the From syntax.""" - return '' - - class VarImpl(object): - def __init__(self, custom_vars, local_scope): - self._custom_vars = custom_vars - self._local_scope = local_scope - - def Lookup(self, var_name): - """Implements the Var syntax.""" - if var_name in self._custom_vars: - return self._custom_vars[var_name] - elif var_name in self._local_scope.get("vars", {}): - return self._local_scope["vars"][var_name] - raise Exception("Var is not defined: %s" % var_name) - - local_scope = {} - var = VarImpl({}, local_scope) - global_scope = { - 'File': FileImplStub, - 'From': from_stub, - 'Var': var.Lookup, - 'deps_os': {}, - } - execfile(deps_file_path, global_scope, local_scope) - deps = local_scope.get('deps', {}) - deps_os = local_scope.get('deps_os', {}) - for os_specific_deps in deps_os.itervalues(): - deps.update(os_specific_deps) - return deps.keys() - - def _get_known_issues(self): - issues = [] - for root, paths in known_issues.KNOWN_INCOMPATIBLE.items(): - for path in paths: - issues.append(os.path.normpath(os.path.join(root, path))) - return issues - - def _make_gclient_blacklist(self, deps_file_path, whitelisted_deps): - """Calculates the list of deps that need to be excluded from the deps_file - so that the only deps left are the one in the whitelist.""" - all_deps = self._read_deps_file(deps_file_path) - # The list of deps read from the DEPS file are prefixed with the source - # tree root, which is 'src' for Chromium. - def prepend_root(path): - return os.path.join('src', path) - whitelisted_deps = map(prepend_root, whitelisted_deps) - deps_blacklist = set(all_deps).difference(set(whitelisted_deps)) - return dict(map(lambda(x): (x, None), deps_blacklist)) - - def _make_blacklist(self, deps_file_path, whitelisted_deps): - """Calculates the list of paths we should exclude """ - all_deps = self._read_deps_file(deps_file_path) - def remove_src_prefix(path): - return path.replace('src/', '', 1) - all_deps = map(remove_src_prefix, all_deps) - # Ignore all deps except those whitelisted. - blacklist = set(all_deps).difference(whitelisted_deps) - # Ignore the 'known issues'. Typically these are the licence incompatible - # things checked directly into Chromium. - blacklist = blacklist.union(self._get_known_issues()) - # Ignore any other non-deps, non-licence paths we don't like. - blacklist = blacklist.union(self._prune_from_rsync_build) - return list(blacklist) - - def get_deps_for_android_build(self, deps_file_path): - """This is used to calculate the custom_deps list for the Android bot. - """ - if not deps_file_path: - raise Exception('You need to specify a DEPS file path.') - return self._make_gclient_blacklist(deps_file_path, - self._compile_dependencies) - - def get_deps_for_android_build_and_test(self, deps_file_path): - """This is used to calculate the custom_deps list for the Android perf bot. - """ - if not deps_file_path: - raise Exception('You need to specify a DEPS file path.') - return self._make_gclient_blacklist(deps_file_path, - self._compile_dependencies + - self._test_data_dependencies) - - def get_blacklist_for_android_rsync_build(self, deps_file_path): - """Calculates the list of paths we should exclude when building Android - either because of license compatibility or because they are large and - uneeded. - """ - if not deps_file_path: - raise Exception('You need to specify a DEPS file path.') - return self._make_blacklist(deps_file_path, self._compile_dependencies) - - def get_deps_for_android_merge(self, _): - """Calculates the list of deps that need to be merged into the Android tree - in order to build the C++ and Java android_webview code.""" - return self._snapshot_into_android_dependencies - - def get_deps_for_license_check(self, _): - """Calculates the list of deps that need to be checked for Android license - compatibility""" - return self._compile_dependencies - - - def execute_method(self, method_name, deps_file_path): - methods = { - 'android_build': self.get_deps_for_android_build, - 'android_build_and_test': - self.get_deps_for_android_build_and_test, - 'android_merge': self.get_deps_for_android_merge, - 'license_check': self.get_deps_for_license_check, - 'android_rsync_build': self.get_blacklist_for_android_rsync_build, - } - if not method_name in methods: - raise Exception('Method name %s is not valid. Valid choices are %s' % - (method_name, methods.keys())) - return methods[method_name](deps_file_path) - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--method', help='Method to use to fetch from whitelist.', - required=True) - parser.add_argument('--path-to-deps', help='Path to DEPS file.') - parser.add_argument('--output-json', help='Name of file to write output to.') - parser.add_argument('verbose', action='store_true', default=False) - opts = parser.parse_args() - - logging.getLogger().setLevel(logging.DEBUG if opts.verbose else logging.WARN) - - deps_whitelist = DepsWhitelist() - blacklist = deps_whitelist.execute_method(opts.method, opts.path_to_deps) - - if (opts.output_json): - output_dict = { - 'blacklist' : blacklist - } - with open(opts.output_json, 'w') as output_json_file: - json.dump(output_dict, output_json_file) - else: - print blacklist - - return 0 - - -if __name__ == '__main__': - sys.exit(main())
diff --git a/android_webview/buildbot/generate_local_manifest.py b/android_webview/buildbot/generate_local_manifest.py deleted file mode 100755 index 59cb2de..0000000 --- a/android_webview/buildbot/generate_local_manifest.py +++ /dev/null
@@ -1,100 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Generate local manifest in an Android repository. - -This is used to generate a local manifest in an Android repository. The purpose -of the generated manifest is to remove the set of projects that exist under a -certain path. -""" - -from optparse import OptionParser -import os -import xml.etree.ElementTree as ET - -def createLocalManifest(manifest_path, local_manifest_path, path_to_exclude, - pinned_projects=None): - manifest_tree = ET.parse(manifest_path) - local_manifest_root = ET.Element('manifest') - - def remove_project(project): - remove_project = ET.SubElement(local_manifest_root, 'remove-project') - remove_project.set('name', project.get('name')) - - def pin_project(project, revision): - pin_project = ET.SubElement(local_manifest_root, 'project') - pin_project.set('name', project.get('name')) - if project.get('path') != None: - pin_project.set('path', project.get('path')) - pin_project.set('revision', revision) - - for project in manifest_tree.getroot().findall('project'): - project_path = project.get('path') - project_name = project.get('name') - exclude_project = ((project_path != None and - project_path.startswith(path_to_exclude)) or - (project_path == None and - project_name.startswith(path_to_exclude))) - if exclude_project: - print 'Excluding project name="%s" path="%s"' % (project_name, - project_path) - remove_project(project) - continue - - pinned_projects = pinned_projects or [] - for pinned in pinned_projects: - if pinned['path'] == project_path and pinned['name'] == project_name: - remove_project(project) - pin_project(project, pinned['revision']) - break - - local_manifest_tree = ET.ElementTree(local_manifest_root) - local_manifest_dir = os.path.dirname(local_manifest_path) - if not os.path.exists(local_manifest_dir): - os.makedirs(local_manifest_dir) - local_manifest_tree.write(local_manifest_path, - xml_declaration=True, - encoding='UTF-8', - method='xml') - -def main(): - usage = 'usage: %prog [options] <android_build_top> <path_to_exclude>' - parser = OptionParser(usage=usage) - parser.add_option('--ndk-revision', dest='ndk_revision', - help='pin the ndk project at a particular REVISION', - metavar='REVISION', default=None) - parser.add_option('--manifest_filename', dest='manifest_filename', - help='name of the manifest file', default='default.xml') - (options, args) = parser.parse_args() - - if len(args) != 2: - parser.error('Wrong number of arguments.') - - android_build_top = args[0] - path_to_exclude = args[1] - - manifest_filename = options.manifest_filename - - manifest_path = os.path.join(android_build_top, '.repo/manifests', - manifest_filename) - local_manifest_path = os.path.join(android_build_top, - '.repo/local_manifest.xml') - - pinned_projects = [] - if options.ndk_revision: - pinned_projects = [{ - 'path': 'ndk', - 'name': 'platform/ndk', - 'revision' : options.ndk_revision, - },] - - print 'Path to exclude: %s' % path_to_exclude - print 'Path to manifest file: %s' % manifest_path - createLocalManifest(manifest_path, local_manifest_path, path_to_exclude, - pinned_projects) - print 'Local manifest created in: %s' % local_manifest_path - -if __name__ == '__main__': - main()
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/ResourcesContextWrapperFactory.java b/android_webview/glue/java/src/com/android/webview/chromium/ResourcesContextWrapperFactory.java index a6e58a32..a802246 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/ResourcesContextWrapperFactory.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/ResourcesContextWrapperFactory.java
@@ -11,87 +11,83 @@ import org.chromium.base.annotations.SuppressFBWarnings; -import java.util.WeakHashMap; - /** * This class allows us to wrap the application context so that the WebView implementation can * correctly reference both org.chromium.* and application classes which is necessary to properly - * inflate UI. We keep a weak map from contexts to wrapped contexts to avoid constantly re-wrapping - * or doubly wrapping contexts. + * inflate UI. */ public class ResourcesContextWrapperFactory { - private static WeakHashMap<Context, ContextWrapper> sCtxToWrapper = - new WeakHashMap<Context, ContextWrapper>(); - private static final Object sLock = new Object(); - private ResourcesContextWrapperFactory() {} public static Context get(Context ctx) { - ContextWrapper wrappedCtx; - synchronized (sLock) { - wrappedCtx = sCtxToWrapper.get(ctx); - if (wrappedCtx == null) { - wrappedCtx = createWrapper(ctx); - sCtxToWrapper.put(ctx, wrappedCtx); - } + // Avoid double-wrapping a context. + if (ctx instanceof WebViewContextWrapper) { + return ctx; } - return wrappedCtx; + return new WebViewContextWrapper(ctx); } - private static ContextWrapper createWrapper(final Context ctx) { - return new ContextWrapper(ctx) { - private Context mApplicationContext; + private static class WebViewContextWrapper extends ContextWrapper { + private Context mApplicationContext; - @SuppressFBWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED") - @Override - public ClassLoader getClassLoader() { - final ClassLoader appCl = getBaseContext().getClassLoader(); - final ClassLoader webViewCl = this.getClass().getClassLoader(); - return new ClassLoader() { - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - // First look in the WebViewProvider class loader. - try { - return webViewCl.loadClass(name); - } catch (ClassNotFoundException e) { - // Look in the app class loader; allowing it to throw - // ClassNotFoundException. - return appCl.loadClass(name); - } + public WebViewContextWrapper(Context base) { + super(base); + } + + @SuppressFBWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED") + @Override + public ClassLoader getClassLoader() { + final ClassLoader appCl = getBaseContext().getClassLoader(); + final ClassLoader webViewCl = this.getClass().getClassLoader(); + return new ClassLoader() { + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + // First look in the WebViewProvider class loader. + try { + return webViewCl.loadClass(name); + } catch (ClassNotFoundException e) { + // Look in the app class loader; allowing it to throw + // ClassNotFoundException. + return appCl.loadClass(name); } - }; - } + } + }; + } - @Override - public Object getSystemService(String name) { - if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) { - LayoutInflater i = (LayoutInflater) getBaseContext().getSystemService(name); - return i.cloneInContext(this); + @Override + public Object getSystemService(String name) { + if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) { + LayoutInflater i = (LayoutInflater) getBaseContext().getSystemService(name); + return i.cloneInContext(this); + } else { + return getBaseContext().getSystemService(name); + } + } + + @Override + public Context getApplicationContext() { + if (mApplicationContext == null) { + Context appCtx = getBaseContext().getApplicationContext(); + if (appCtx == getBaseContext()) { + mApplicationContext = this; } else { - return getBaseContext().getSystemService(name); + mApplicationContext = get(appCtx); } } + return mApplicationContext; + } - @Override - public Context getApplicationContext() { - if (mApplicationContext == null) { - mApplicationContext = get(ctx.getApplicationContext()); - } - return mApplicationContext; - } + @Override + public void registerComponentCallbacks(ComponentCallbacks callback) { + // We have to override registerComponentCallbacks and unregisterComponentCallbacks + // since they call getApplicationContext().[un]registerComponentCallbacks() + // which causes us to go into a loop. + getBaseContext().registerComponentCallbacks(callback); + } - @Override - public void registerComponentCallbacks(ComponentCallbacks callback) { - // We have to override registerComponentCallbacks and unregisterComponentCallbacks - // since they call getApplicationContext().[un]registerComponentCallbacks() - // which causes us to go into a loop. - ctx.registerComponentCallbacks(callback); - } - - @Override - public void unregisterComponentCallbacks(ComponentCallbacks callback) { - ctx.unregisterComponentCallbacks(callback); - } - }; + @Override + public void unregisterComponentCallbacks(ComponentCallbacks callback) { + getBaseContext().unregisterComponentCallbacks(callback); + } } }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index 5d3d668..041ffe2 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -79,6 +79,7 @@ private WebStorageAdapter mWebStorage; private WebViewDatabaseAdapter mWebViewDatabase; private AwDevToolsServer mDevToolsServer; + private Context mWrappedAppContext; private ArrayList<WeakReference<WebViewChromium>> mWebViewsToStart = new ArrayList<WeakReference<WebViewChromium>>(); @@ -291,7 +292,11 @@ } private Context getWrappedCurrentApplicationContext() { - return ResourcesContextWrapperFactory.get(mWebViewDelegate.getApplication()); + if (mWrappedAppContext == null) { + mWrappedAppContext = ResourcesContextWrapperFactory.get( + mWebViewDelegate.getApplication()); + } + return mWrappedAppContext; } AwBrowserContext getBrowserContext() {
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc index 27e5da9..8520816 100644 --- a/android_webview/lib/main/aw_main_delegate.cc +++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -195,7 +195,7 @@ content::ExternalVideoSurfaceContainer* AwMainDelegate::CreateExternalVideoSurfaceContainer( content::WebContents* web_contents) { - return new ExternalVideoSurfaceContainerImpl(web_contents); + return ExternalVideoSurfaceContainerImpl::Create(web_contents); } #endif
diff --git a/android_webview/native/external_video_surface_container_impl.cc b/android_webview/native/external_video_surface_container_impl.cc index 84d5ad4..64270ef 100644 --- a/android_webview/native/external_video_surface_container_impl.cc +++ b/android_webview/native/external_video_surface_container_impl.cc
@@ -14,15 +14,23 @@ namespace android_webview { -ExternalVideoSurfaceContainerImpl::ExternalVideoSurfaceContainerImpl( +// static +ExternalVideoSurfaceContainerImpl* ExternalVideoSurfaceContainerImpl::Create( content::WebContents* web_contents) { ContentViewCore* cvc = ContentViewCore::FromWebContents(web_contents); - if (cvc) { - JNIEnv* env = AttachCurrentThread(); - jobject_.Reset( - Java_ExternalVideoSurfaceContainer_create( - env, reinterpret_cast<intptr_t>(this), cvc->GetJavaObject().obj())); - } + if (!cvc) + return nullptr; + base::android::ScopedJavaLocalRef<jobject> jcvc = cvc->GetJavaObject(); + if (jcvc.is_null()) + return nullptr; + return new ExternalVideoSurfaceContainerImpl(jcvc); +} + +ExternalVideoSurfaceContainerImpl::ExternalVideoSurfaceContainerImpl( + base::android::ScopedJavaLocalRef<jobject> java_content_view_core) { + JNIEnv* env = AttachCurrentThread(); + jobject_.Reset(Java_ExternalVideoSurfaceContainer_create( + env, reinterpret_cast<intptr_t>(this), java_content_view_core.obj())); } ExternalVideoSurfaceContainerImpl::~ExternalVideoSurfaceContainerImpl() {
diff --git a/android_webview/native/external_video_surface_container_impl.h b/android_webview/native/external_video_surface_container_impl.h index 29e7889..48ccd94 100644 --- a/android_webview/native/external_video_surface_container_impl.h +++ b/android_webview/native/external_video_surface_container_impl.h
@@ -20,7 +20,8 @@ typedef base::Callback<void(int, jobject)> SurfaceCreatedCB; typedef base::Callback<void(int)> SurfaceDestroyedCB; - ExternalVideoSurfaceContainerImpl(content::WebContents* contents); + static ExternalVideoSurfaceContainerImpl* Create( + content::WebContents* web_contents); // ExternalVideoSurfaceContainer implementation. void RequestExternalVideoSurface( @@ -39,6 +40,8 @@ void SurfaceDestroyed(JNIEnv* env, jobject obj, jint player_id); private: + explicit ExternalVideoSurfaceContainerImpl( + base::android::ScopedJavaLocalRef<jobject> java_content_view_core); ~ExternalVideoSurfaceContainerImpl() override; base::android::ScopedJavaGlobalRef<jobject> jobject_;
diff --git a/ash/ash.gyp b/ash/ash.gyp index bead4a60..e0f39d5 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -603,8 +603,6 @@ 'wm/toplevel_window_event_handler.h', 'wm/video_detector.cc', 'wm/video_detector.h', - 'wm/virtual_keyboard_container_layout_manager.cc', - 'wm/virtual_keyboard_container_layout_manager.h', 'wm/window_animations.cc', 'wm/window_animations.h', 'wm/window_cycle_controller.cc',
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc index 773fe5c..ed1f0af 100644 --- a/ash/display/cursor_window_controller.cc +++ b/ash/display/cursor_window_controller.cc
@@ -16,7 +16,6 @@ #include "ui/base/hit_test.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/dip_util.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/gfx/canvas.h" #include "ui/gfx/display.h"
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index ac1cf3b..c1c9e63 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc
@@ -4,10 +4,7 @@ #include "ash/metrics/user_metrics_recorder.h" -#include "ash/shelf/shelf_delegate.h" -#include "ash/shelf/shelf_item_types.h" #include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_model.h" #include "ash/shelf/shelf_view.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" @@ -124,29 +121,6 @@ return visible_window_count; } -void RecordShelfItemCounts() { - ShelfDelegate* shelf_delegate = Shell::GetInstance()->GetShelfDelegate(); - int pinned_item_count = 0; - int unpinned_item_count = 0; - - for (const ShelfItem& shelf_item : - Shell::GetInstance()->shelf_model()->items()) { - if (shelf_item.type != TYPE_APP_LIST) { - if (shelf_delegate->IsAppPinned( - shelf_delegate->GetAppIDForShelfID(shelf_item.id))) - ++pinned_item_count; - else - ++unpinned_item_count; - } - } - - UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfItems", - pinned_item_count + unpinned_item_count); - UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfPinnedItems", pinned_item_count); - UMA_HISTOGRAM_COUNTS_100("Ash.Shelf.NumberOfUnpinnedItems", - unpinned_item_count); -} - } // namespace UserMetricsRecorder::UserMetricsRecorder() { @@ -561,8 +535,6 @@ UMA_HISTOGRAM_ENUMERATION("Ash.ActiveWindowShowTypeOverTime", GetActiveWindowState(), ACTIVE_WINDOW_STATE_TYPE_COUNT); - - RecordShelfItemCounts(); } } // namespace ash
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index 1a56f5e..3bb279b 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc
@@ -44,7 +44,6 @@ #include "ash/wm/status_area_layout_manager.h" #include "ash/wm/system_background_controller.h" #include "ash/wm/system_modal_container_layout_manager.h" -#include "ash/wm/virtual_keyboard_container_layout_manager.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" @@ -635,9 +634,6 @@ keyboard_controller->GetContainerWindow(); keyboard_container->set_id(kShellWindowId_VirtualKeyboardContainer); parent->AddChild(keyboard_container); - // TODO(oshima): Bounds of keyboard container should be handled by - // RootWindowLayoutManager. Remove this after fixed RootWindowLayoutManager. - keyboard_container->SetBounds(parent->bounds()); } void RootWindowController::DeactivateKeyboard( @@ -993,9 +989,6 @@ lock_screen_related_containers); wm::SetSnapsChildrenToPhysicalPixelBoundary( virtual_keyboard_parent_container); - virtual_keyboard_parent_container->SetLayoutManager( - new VirtualKeyboardContainerLayoutManager( - virtual_keyboard_parent_container)); SetUsesScreenCoordinates(virtual_keyboard_parent_container); aura::Window* menu_container = CreateContainer(
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc index b29ccff..8c5c516 100644 --- a/ash/root_window_controller_unittest.cc +++ b/ash/root_window_controller_unittest.cc
@@ -744,15 +744,14 @@ aura::Window* keyboard_window = controller->proxy()->GetKeyboardWindow(); keyboard_container->AddChild(keyboard_window); keyboard_window->set_owned_by_parent(false); - keyboard_window->SetBounds(keyboard::KeyboardBoundsFromWindowBounds( - keyboard_container->bounds(), 100)); + keyboard_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds( + root_window->bounds(), 100)); keyboard_window->Show(); gfx::Rect before = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); // Notify keyboard bounds changing. - controller->NotifyKeyboardBoundsChanging( - controller->proxy()->GetKeyboardWindow()->bounds()); + controller->NotifyKeyboardBoundsChanging(keyboard_container->bounds()); if (!keyboard::IsKeyboardOverscrollEnabled()) { gfx::Rect after = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); @@ -777,8 +776,8 @@ proxy()->GetKeyboardWindow(); keyboard_container->AddChild(keyboard_window); keyboard_window->set_owned_by_parent(false); - keyboard_window->SetBounds(keyboard::KeyboardBoundsFromWindowBounds( - keyboard_container->bounds(), 100)); + keyboard_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds( + root_window->bounds(), 100)); ui::test::TestEventHandler handler; root_window->AddPreTargetHandler(&handler); @@ -833,13 +832,13 @@ aura::Window* keyboard_window =proxy->GetKeyboardWindow(); keyboard_container->AddChild(keyboard_window); keyboard_window->set_owned_by_parent(false); - keyboard_window->SetBounds(keyboard::KeyboardBoundsFromWindowBounds( - keyboard_container->bounds(), keyboard_height)); + keyboard_window->SetBounds(keyboard::FullWidthKeyboardBoundsFromRootBounds( + root_window->bounds(), keyboard_height)); proxy->EnsureCaretInWorkArea(); - ASSERT_EQ(keyboard_container->bounds().width(), + ASSERT_EQ(root_window->bounds().width(), text_input_client.visible_rect().width()); - ASSERT_EQ(keyboard_container->bounds().height() - keyboard_height, + ASSERT_EQ(root_window->bounds().height() - keyboard_height, text_input_client.visible_rect().height()); if (switches::IsTextInputFocusManagerEnabled()) { @@ -869,8 +868,8 @@ aura::Window* keyboard_window = proxy->GetKeyboardWindow(); keyboard_container->AddChild(keyboard_window); keyboard_window->set_owned_by_parent(false); - gfx::Rect keyboard_bounds = keyboard::KeyboardBoundsFromWindowBounds( - keyboard_container->bounds(), keyboard_height); + gfx::Rect keyboard_bounds = keyboard::FullWidthKeyboardBoundsFromRootBounds( + root_window->bounds(), keyboard_height); keyboard_window->SetBounds(keyboard_bounds); keyboard_window->Show(); @@ -952,11 +951,15 @@ aura::Window* keyboard_container = Shell::GetContainer(root_window, kShellWindowId_VirtualKeyboardContainer); ASSERT_TRUE(keyboard_container); - keyboard_container->Show(); - EXPECT_EQ("0,0 800x600", keyboard_container->bounds().ToString()); + keyboard::KeyboardController* keyboard_controller = + keyboard::KeyboardController::GetInstance(); + keyboard_controller->ShowKeyboard(false); + keyboard_controller->proxy()->GetKeyboardWindow()->SetBounds( + gfx::Rect(0, 400, 800, 200)); + EXPECT_EQ("0,400 800x200", keyboard_container->bounds().ToString()); UpdateDisplay("600x800"); - EXPECT_EQ("0,0 600x800", keyboard_container->bounds().ToString()); + EXPECT_EQ("0,600 600x200", keyboard_container->bounds().ToString()); } } // namespace test
diff --git a/ash/shell.cc b/ash/shell.cc index ee93a342..6bf50fe0 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -678,7 +678,6 @@ RemovePreTargetHandler(speech_feedback_handler_.get()); speech_feedback_handler_.reset(); #endif - RemovePreTargetHandler(user_activity_detector_.get()); RemovePreTargetHandler(overlay_filter_.get()); RemovePreTargetHandler(input_method_filter_.get()); RemovePreTargetHandler(accelerator_filter_.get()); @@ -922,7 +921,6 @@ // ui::UserActivityDetector passes events to observers, so let them get // rewritten first. user_activity_detector_.reset(new ui::UserActivityDetector); - AddPreTargetHandler(user_activity_detector_.get()); overlay_filter_.reset(new OverlayEventFilter); AddPreTargetHandler(overlay_filter_.get());
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index dc081c6..4af993a 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc
@@ -181,6 +181,10 @@ return false; } +bool ShellDelegateImpl::IsForceMaximizeOnFirstRun() const { + return false; +} + void ShellDelegateImpl::PreInit() { }
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h index 502161de..255401a5 100644 --- a/ash/shell/shell_delegate_impl.h +++ b/ash/shell/shell_delegate_impl.h
@@ -39,6 +39,7 @@ bool IsMultiProfilesEnabled() const override; bool IsRunningInForcedAppMode() const override; bool IsMultiAccountEnabled() const override; + bool IsForceMaximizeOnFirstRun() const override; void PreInit() override; void PreShutdown() override; void Exit() override;
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h index 148f686..64f8139 100644 --- a/ash/shell_delegate.h +++ b/ash/shell_delegate.h
@@ -83,6 +83,11 @@ // Returns true if multi account is enabled. virtual bool IsMultiAccountEnabled() const = 0; + // Returns true if the first window shown on first run should be + // unconditionally maximized, overriding the heuristic that normally chooses + // the window size. + virtual bool IsForceMaximizeOnFirstRun() const = 0; + // Called before processing |Shell::Init()| so that the delegate // can perform tasks necessary before the shell is initialized. virtual void PreInit() = 0;
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc index 9b11604..ee6fd44a 100644 --- a/ash/test/test_shell_delegate.cc +++ b/ash/test/test_shell_delegate.cc
@@ -82,6 +82,7 @@ TestShellDelegate::TestShellDelegate() : num_exit_requests_(0), multi_profiles_enabled_(false), + force_maximize_on_first_run_(false), test_session_state_delegate_(NULL) { } @@ -108,6 +109,10 @@ return false; } +bool TestShellDelegate::IsForceMaximizeOnFirstRun() const { + return force_maximize_on_first_run_; +} + void TestShellDelegate::PreInit() { }
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h index 95e9487..9b273fc9 100644 --- a/ash/test/test_shell_delegate.h +++ b/ash/test/test_shell_delegate.h
@@ -36,6 +36,7 @@ bool IsMultiProfilesEnabled() const override; bool IsRunningInForcedAppMode() const override; bool IsMultiAccountEnabled() const override; + bool IsForceMaximizeOnFirstRun() const override; void PreInit() override; void PreShutdown() override; void Exit() override; @@ -63,10 +64,14 @@ int num_exit_requests() const { return num_exit_requests_; } void SetMediaCaptureState(MediaCaptureState state); + void SetForceMaximizeOnFirstRun(bool maximize) { + force_maximize_on_first_run_ = maximize; + }; private: int num_exit_requests_; bool multi_profiles_enabled_; + bool force_maximize_on_first_run_; scoped_ptr<content::BrowserContext> active_browser_context_; scoped_ptr<app_list::AppListViewDelegate> app_list_view_delegate_;
diff --git a/ash/utility/partial_screenshot_controller.cc b/ash/utility/partial_screenshot_controller.cc index 661d405..f2406d9 100644 --- a/ash/utility/partial_screenshot_controller.cc +++ b/ash/utility/partial_screenshot_controller.cc
@@ -10,7 +10,6 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "base/stl_util.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event_handler.h" #include "ui/gfx/canvas.h"
diff --git a/ash/wm/always_on_top_controller_unittest.cc b/ash/wm/always_on_top_controller_unittest.cc index 535ed5f..f2db7e01 100644 --- a/ash/wm/always_on_top_controller_unittest.cc +++ b/ash/wm/always_on_top_controller_unittest.cc
@@ -79,8 +79,8 @@ keyboard_container->AddChild(keyboard_window); keyboard_window->set_owned_by_parent(false); const int kKeyboardHeight = 200; - gfx::Rect keyboard_bounds = keyboard::KeyboardBoundsFromWindowBounds( - keyboard_container->bounds(), kKeyboardHeight); + gfx::Rect keyboard_bounds = keyboard::FullWidthKeyboardBoundsFromRootBounds( + root_window->bounds(), kKeyboardHeight); keyboard_window->SetBounds(keyboard_bounds); keyboard_window->Show(); keyboard_controller->NotifyKeyboardBoundsChanging(keyboard_bounds);
diff --git a/ash/wm/boot_splash_screen_chromeos.cc b/ash/wm/boot_splash_screen_chromeos.cc index 0c3cb54..342285d 100644 --- a/ash/wm/boot_splash_screen_chromeos.cc +++ b/ash/wm/boot_splash_screen_chromeos.cc
@@ -10,7 +10,6 @@ #include "ui/base/x/x11_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_type.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/canvas.h"
diff --git a/ash/wm/dock/docked_window_layout_manager.cc b/ash/wm/dock/docked_window_layout_manager.cc index 6845195..91fe6c8 100644 --- a/ash/wm/dock/docked_window_layout_manager.cc +++ b/ash/wm/dock/docked_window_layout_manager.cc
@@ -31,7 +31,6 @@ #include "ui/aura/window_delegate.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/canvas.h"
diff --git a/ash/wm/lock_layout_manager_unittest.cc b/ash/wm/lock_layout_manager_unittest.cc index fc097fb3..96ce1a84 100644 --- a/ash/wm/lock_layout_manager_unittest.cc +++ b/ash/wm/lock_layout_manager_unittest.cc
@@ -93,8 +93,8 @@ keyboard->ShowKeyboard(true); if (keyboard->proxy()->GetKeyboardWindow()->bounds().height() == 0) { keyboard->proxy()->GetKeyboardWindow()->SetBounds( - keyboard::KeyboardBoundsFromWindowBounds( - keyboard->GetContainerWindow()->bounds(), + keyboard::FullWidthKeyboardBoundsFromRootBounds( + Shell::GetPrimaryRootWindow()->bounds(), kVirtualKeyboardHeight)); } } else {
diff --git a/ash/wm/system_modal_container_layout_manager_unittest.cc b/ash/wm/system_modal_container_layout_manager_unittest.cc index 1f74726..6229587 100644 --- a/ash/wm/system_modal_container_layout_manager_unittest.cc +++ b/ash/wm/system_modal_container_layout_manager_unittest.cc
@@ -182,8 +182,8 @@ keyboard->ShowKeyboard(true); if (keyboard->proxy()->GetKeyboardWindow()->bounds().height() == 0) { keyboard->proxy()->GetKeyboardWindow()->SetBounds( - keyboard::KeyboardBoundsFromWindowBounds( - keyboard->GetContainerWindow()->bounds(), 100)); + keyboard::FullWidthKeyboardBoundsFromRootBounds( + Shell::GetPrimaryRootWindow()->bounds(), 100)); } } else { keyboard->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL);
diff --git a/ash/wm/virtual_keyboard_container_layout_manager.cc b/ash/wm/virtual_keyboard_container_layout_manager.cc deleted file mode 100644 index aae3ec8..0000000 --- a/ash/wm/virtual_keyboard_container_layout_manager.cc +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/wm/virtual_keyboard_container_layout_manager.h" - -#include "ash/shell_window_ids.h" -#include "ui/aura/window.h" -#include "ui/keyboard/keyboard_controller.h" - -namespace ash { - -//////////////////////////////////////////////////////////////////////////////// -// VirtualKeyboardContainerLayoutManager, public: - -VirtualKeyboardContainerLayoutManager::VirtualKeyboardContainerLayoutManager( - aura::Window* container) - : SnapToPixelLayoutManager(container), - parent_container_(container) {} - -VirtualKeyboardContainerLayoutManager::~VirtualKeyboardContainerLayoutManager() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// VirtualKeyboardContainerLayoutManager, aura::LayoutManager implementation: - -void VirtualKeyboardContainerLayoutManager::OnWindowResized() { - keyboard::KeyboardController* keyboard_controller = - keyboard::KeyboardController::GetInstance(); - if (!keyboard_controller) - return; - - // The layout manager for the root window propagates a resize to its - // immediate children and grandchildren, but stops there. The keyboard - // container is three levels deep, and therefore needs to be explicitly - // updated when its parent is resized. - aura::Window* keyboard_container = - keyboard_controller->GetContainerWindow(); - if (keyboard_container) - keyboard_container->SetBounds(parent_container_->bounds()); -} - -} // namespace ash
diff --git a/ash/wm/virtual_keyboard_container_layout_manager.h b/ash/wm/virtual_keyboard_container_layout_manager.h deleted file mode 100644 index 13fda64..0000000 --- a/ash/wm/virtual_keyboard_container_layout_manager.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_WM_VIRTUAL_KEYBOARD_CONTAINER_LAYOUT_MANAGER_H_ -#define ASH_WM_VIRTUAL_KEYBOARD_CONTAINER_LAYOUT_MANAGER_H_ - -#include "ash/snap_to_pixel_layout_manager.h" -#include "base/macros.h" - -namespace aura { -class Window; -} - -namespace ash { - -class VirtualKeyboardContainerLayoutManager : public SnapToPixelLayoutManager { - public: - explicit VirtualKeyboardContainerLayoutManager(aura::Window* container); - ~VirtualKeyboardContainerLayoutManager() override; - - // Overridden from SnapToPixelLayoutManager: - void OnWindowResized() override; - - private: - aura::Window* parent_container_; - - DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardContainerLayoutManager); -}; - -} // namespace ash - -#endif // ASH_WM_VIRTUAL_KEYBOARD_CONTAINER_LAYOUT_MANAGER_H_ \ No newline at end of file
diff --git a/ash/wm/window_positioner.cc b/ash/wm/window_positioner.cc index 4e80ed84..eed15a0 100644 --- a/ash/wm/window_positioner.cc +++ b/ash/wm/window_positioner.cc
@@ -6,6 +6,7 @@ #include "ash/screen_util.h" #include "ash/shell.h" +#include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/window_resizer.h" @@ -246,7 +247,6 @@ ui::WindowShowState show_state_in, gfx::Rect* bounds_in_out, ui::WindowShowState* show_state_out) { - // Always open new window in the target display. aura::Window* target = Shell::GetTargetRootWindow(); @@ -264,14 +264,24 @@ // Use adjusted saved bounds, if there is one. if (is_saved_bounds) return; - // When using "small screens" we want to always open in full screen mode. - if (show_state_in == ui::SHOW_STATE_DEFAULT && (maximize_first_window || - (work_area.width() <= GetForceMaximizedWidthLimit() && - (!new_window || !wm::GetWindowState(new_window)->IsFullscreen())))) { - *show_state_out = ui::SHOW_STATE_MAXIMIZED; + + if (show_state_in == ui::SHOW_STATE_DEFAULT) { + const bool maximize_first_window_on_first_run = + Shell::GetInstance()->delegate()->IsForceMaximizeOnFirstRun(); + // We want to always open maximized on "small screens" or when policy + // tells us to. + const bool set_maximized = + maximize_first_window || + ((work_area.width() <= GetForceMaximizedWidthLimit() || + maximize_first_window_on_first_run) && + (!new_window || !wm::GetWindowState(new_window)->IsFullscreen())); + + if (set_maximized) + *show_state_out = ui::SHOW_STATE_MAXIMIZED; } return; } + wm::WindowState* top_window_state = wm::GetWindowState(top_window); bool maximized = top_window_state->IsMaximized(); // We ignore the saved show state, but look instead for the top level
diff --git a/ash/wm/window_positioner_unittest.cc b/ash/wm/window_positioner_unittest.cc index af320bc..79f9a84 100644 --- a/ash/wm/window_positioner_unittest.cc +++ b/ash/wm/window_positioner_unittest.cc
@@ -4,11 +4,15 @@ #include "ash/wm/window_positioner.h" +#include <string> + #include "ash/shell.h" #include "ash/shell/toplevel_window.h" #include "ash/test/ash_test_base.h" +#include "ash/test/test_shell_delegate.h" #include "ash/wm/window_positioner.h" #include "ash/wm/window_state.h" +#include "base/strings/string_number_conversions.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" @@ -146,4 +150,49 @@ widget->CloseNow(); } +// In general case on first run the browser window will be maximized only for +// low resolution screens (width < 1366). In case of big screens the browser is +// opened being not maximized. To enforce maximization for all screen +// resolutions, one can set "ForceMaximizeBrowserWindowOnFirstRun" +// policy. In the following tests we check if the window will be opened in +// maximized mode for low and high resolution when this policy is set. +TEST_F(WindowPositionerTest, FirstRunMaximizeWindowHighResloution) { + const int width = ash::WindowPositioner::GetForceMaximizedWidthLimit() + 100; + // Set resolution to 1466x300. + const std::string resolution = base::IntToString(width) + "x300"; + UpdateDisplay(resolution); + gfx::Rect bounds_in_out(0, 0, 320, 240); // Random bounds. + ui::WindowShowState show_state_out = ui::SHOW_STATE_DEFAULT; + + test::TestShellDelegate* const delegate = + static_cast<test::TestShellDelegate*>(Shell::GetInstance()->delegate()); + delegate->SetForceMaximizeOnFirstRun(true); + + WindowPositioner::GetBoundsAndShowStateForNewWindow( + Shell::GetScreen(), nullptr, false, ui::SHOW_STATE_DEFAULT, + &bounds_in_out, &show_state_out); + + EXPECT_EQ(show_state_out, ui::SHOW_STATE_MAXIMIZED); +} + +// For detail see description of FirstRunMaximizeWindowHighResloution. +TEST_F(WindowPositionerTest, FirstRunMaximizeWindowLowResolution) { + const int width = ash::WindowPositioner::GetForceMaximizedWidthLimit() - 100; + // Set resolution to 1266x300. + const std::string resolution = base::IntToString(width) + "x300"; + UpdateDisplay(resolution); + gfx::Rect bounds_in_out(0, 0, 320, 240); // Random bounds. + ui::WindowShowState show_state_out = ui::SHOW_STATE_DEFAULT; + + test::TestShellDelegate* const delegate = + static_cast<test::TestShellDelegate*>(Shell::GetInstance()->delegate()); + delegate->SetForceMaximizeOnFirstRun(true); + + WindowPositioner::GetBoundsAndShowStateForNewWindow( + Shell::GetScreen(), nullptr, false, ui::SHOW_STATE_DEFAULT, + &bounds_in_out, &show_state_out); + + EXPECT_EQ(show_state_out, ui::SHOW_STATE_MAXIMIZED); +} + } // namespace
diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java index d08cae3..674273c 100644 --- a/base/android/java/src/org/chromium/base/Log.java +++ b/base/android/java/src/org/chromium/base/Log.java
@@ -122,12 +122,19 @@ * the line number. * @param messageTemplate The message you would like logged. It is to be specified as a format * string. - * @param args Arguments referenced by the format specifiers in the format string. + * @param args Arguments referenced by the format specifiers in the format string. If the last + * one is a {@link Throwable}, its trace will be printed. */ private void verbose(String secondaryTag, String messageTemplate, Object... args) { if (isEnabled(android.util.Log.VERBOSE)) { if (mDebugWithStack) secondaryTag = getCallOrigin(); - android.util.Log.v(mTag, formatLog(secondaryTag, messageTemplate, args)); + String message = formatLog(secondaryTag, messageTemplate, args); + Throwable tr = getThrowableToLog(args); + if (tr != null) { + android.util.Log.v(mTag, message, tr); + } else { + android.util.Log.v(mTag, message); + } } } @@ -190,12 +197,19 @@ * the line number. * @param messageTemplate The message you would like logged. It is to be specified as a format * string. - * @param args Arguments referenced by the format specifiers in the format string. + * @param args Arguments referenced by the format specifiers in the format string. If the last + * one is a {@link Throwable}, its trace will be printed. */ private void debug(String secondaryTag, String messageTemplate, Object... args) { if (isEnabled(android.util.Log.DEBUG)) { if (mDebugWithStack) secondaryTag = getCallOrigin(); - android.util.Log.d(mTag, formatLog(secondaryTag, messageTemplate, args)); + String message = formatLog(secondaryTag, messageTemplate, args); + Throwable tr = getThrowableToLog(args); + if (tr != null) { + android.util.Log.d(mTag, message, tr); + } else { + android.util.Log.d(mTag, message); + } } } @@ -249,11 +263,18 @@ * class where the log call occurs. * @param messageTemplate The message you would like logged. It is to be specified as a format * string. - * @param args Arguments referenced by the format specifiers in the format string. + * @param args Arguments referenced by the format specifiers in the format string. If the last + * one is a {@link Throwable}, its trace will be printed. */ public void i(String secondaryTag, String messageTemplate, Object... args) { if (isEnabled(android.util.Log.INFO)) { - android.util.Log.i(mTag, formatLog(secondaryTag, messageTemplate, args)); + String message = formatLog(secondaryTag, messageTemplate, args); + Throwable tr = getThrowableToLog(args); + if (tr != null) { + android.util.Log.i(mTag, message, tr); + } else { + android.util.Log.i(mTag, message); + } } } @@ -264,11 +285,18 @@ * class where the log call occurs. * @param messageTemplate The message you would like logged. It is to be specified as a format * string. - * @param args Arguments referenced by the format specifiers in the format string. + * @param args Arguments referenced by the format specifiers in the format string. If the last + * one is a {@link Throwable}, its trace will be printed. */ public void w(String secondaryTag, String messageTemplate, Object... args) { if (isEnabled(android.util.Log.WARN)) { - android.util.Log.w(mTag, formatLog(secondaryTag, messageTemplate, args)); + String message = formatLog(secondaryTag, messageTemplate, args); + Throwable tr = getThrowableToLog(args); + if (tr != null) { + android.util.Log.w(mTag, message, tr); + } else { + android.util.Log.w(mTag, message); + } } } @@ -279,14 +307,56 @@ * class where the log call occurs. * @param messageTemplate The message you would like logged. It is to be specified as a format * string. - * @param args Arguments referenced by the format specifiers in the format string. + * @param args Arguments referenced by the format specifiers in the format string. If the last + * one is a {@link Throwable}, its trace will be printed. */ public void e(String secondaryTag, String messageTemplate, Object... args) { if (isEnabled(android.util.Log.ERROR)) { - android.util.Log.e(mTag, formatLog(secondaryTag, messageTemplate, args)); + String message = formatLog(secondaryTag, messageTemplate, args); + Throwable tr = getThrowableToLog(args); + if (tr != null) { + android.util.Log.e(mTag, message, tr); + } else { + android.util.Log.e(mTag, message); + } } } + /** + * What a Terrible Failure: Used for conditions that should never happen, and logged at + * the {@link android.util.Log#ASSERT} level. Depending on the configuration, it might + * terminate the process. + * + * @see android.util.Log#wtf(String, String, Throwable) + * + * @param secondaryTag Used to identify the source of a log message. It usually identifies the + * class where the log call occurs. + * @param messageTemplate The message you would like logged. It is to be specified as a format + * string. + * @param args Arguments referenced by the format specifiers in the format string. If the last + * one is a {@link Throwable}, its trace will be printed. + */ + public void wtf(String secondaryTag, String messageTemplate, Object... args) { + if (isEnabled(android.util.Log.ERROR)) { + String message = formatLog(secondaryTag, messageTemplate, args); + Throwable tr = getThrowableToLog(args); + if (tr != null) { + android.util.Log.wtf(mTag, message, tr); + } else { + android.util.Log.wtf(mTag, message); + } + } + } + + private Throwable getThrowableToLog(Object[] args) { + if (args == null || args.length == 0) return null; + + Object lastArg = args[args.length - 1]; + + if (!(lastArg instanceof Throwable)) return null; + return (Throwable) lastArg; + } + /** Returns a string form of the origin of the log call, to be used as secondary tag.*/ private String getCallOrigin() { StackTraceElement[] st = Thread.currentThread().getStackTrace();
diff --git a/base/compiler_specific.h b/base/compiler_specific.h index 034cf06a..63297dca 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h
@@ -128,13 +128,11 @@ #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) #endif -// Return the byte alignment of the given type (available at compile time). Use -// sizeof(type) prior to checking __alignof to workaround Visual C++ bug: -// http://goo.gl/isH0C +// Return the byte alignment of the given type (available at compile time). // Use like: // ALIGNOF(int32) // this would be 4 #if defined(COMPILER_MSVC) -#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type)) +#define ALIGNOF(type) __alignof(type) #elif defined(COMPILER_GCC) #define ALIGNOF(type) __alignof__(type) #endif
diff --git a/base/memory/manual_constructor.h b/base/memory/manual_constructor.h index 9275f73b..56081a1 100644 --- a/base/memory/manual_constructor.h +++ b/base/memory/manual_constructor.h
@@ -18,6 +18,7 @@ #include <stddef.h> +#include "base/compiler_specific.h" #include "base/memory/aligned_memory.h" namespace base { @@ -33,11 +34,7 @@ // Support users creating arrays of ManualConstructor<>s. This ensures that // the array itself has the correct alignment. static void* operator new[](size_t size) { -#if defined(COMPILER_MSVC) - return AlignedAlloc(size, __alignof(Type)); -#else - return AlignedAlloc(size, __alignof__(Type)); -#endif + return AlignedAlloc(size, ALIGNOF(Type)); } static void operator delete[](void* mem) { AlignedFree(mem); @@ -56,56 +53,9 @@ inline Type& operator*() { return *get(); } inline const Type& operator*() const { return *get(); } - // You can pass up to eight constructor arguments as arguments of Init(). - inline void Init() { - new(space_.void_data()) Type; - } - - template <typename T1> - inline void Init(const T1& p1) { - new(space_.void_data()) Type(p1); - } - - template <typename T1, typename T2> - inline void Init(const T1& p1, const T2& p2) { - new(space_.void_data()) Type(p1, p2); - } - - template <typename T1, typename T2, typename T3> - inline void Init(const T1& p1, const T2& p2, const T3& p3) { - new(space_.void_data()) Type(p1, p2, p3); - } - - template <typename T1, typename T2, typename T3, typename T4> - inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { - new(space_.void_data()) Type(p1, p2, p3, p4); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5> - inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, - const T5& p5) { - new(space_.void_data()) Type(p1, p2, p3, p4, p5); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> - inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, - const T5& p5, const T6& p6) { - new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7> - inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, - const T5& p5, const T6& p6, const T7& p7) { - new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8> - inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, - const T5& p5, const T6& p6, const T7& p7, const T8& p8) { - new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7, p8); + template <typename... Ts> + inline void Init(const Ts&... params) { + new(space_.void_data()) Type(params...); } inline void Destroy() { @@ -113,11 +63,7 @@ } private: -#if defined(COMPILER_MSVC) - AlignedMemory<sizeof(Type), __alignof(Type)> space_; -#else - AlignedMemory<sizeof(Type), __alignof__(Type)> space_; -#endif + AlignedMemory<sizeof(Type), ALIGNOF(Type)> space_; }; } // namespace base
diff --git a/base/observer_list.h b/base/observer_list.h index f7b9267..e473b32 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -154,6 +154,7 @@ template <class ObserverType> void ObserverListBase<ObserverType>::AddObserver(ObserverType* obs) { + DCHECK(obs); if (std::find(observers_.begin(), observers_.end(), obs) != observers_.end()) { NOTREACHED() << "Observers can only be added once!"; @@ -164,6 +165,7 @@ template <class ObserverType> void ObserverListBase<ObserverType>::RemoveObserver(ObserverType* obs) { + DCHECK(obs); typename ListType::iterator it = std::find(observers_.begin(), observers_.end(), obs); if (it != observers_.end()) {
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index ed965fa..ec7651fe 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc
@@ -77,7 +77,7 @@ void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) { AutoLock lock(lock_); - DCHECK(delegate_ == nullptr); + DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_); delegate_ = delegate; }
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc index 32ec75c..a60e260 100644 --- a/base/tracked_objects.cc +++ b/base/tracked_objects.cc
@@ -28,9 +28,6 @@ namespace tracked_objects { namespace { -// Flag to compile out almost all of the task tracking code. -const bool kTrackAllTaskObjects = true; - // TODO(jar): Evaluate the perf impact of enabling this. If the perf impact is // negligible, enable by default. // Flag to compile out parent-child link recording. @@ -366,8 +363,6 @@ DCHECK(thread_data); // TLS should *never* call us with a NULL. // We must NOT do any allocations during this callback. There is a chance // that the allocator is no longer active on this thread. - if (!kTrackAllTaskObjects) - return; // Not compiled in. reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup(); } @@ -465,9 +460,6 @@ // static Births* ThreadData::TallyABirthIfActive(const Location& location) { - if (!kTrackAllTaskObjects) - return NULL; // Not compiled in. - if (!TrackingStatus()) return NULL; ThreadData* current_thread_data = Get(); @@ -480,9 +472,6 @@ void ThreadData::TallyRunOnNamedThreadIfTracking( const base::TrackingInfo& completed_task, const TaskStopwatch& stopwatch) { - if (!kTrackAllTaskObjects) - return; // Not compiled in. - // Even if we have been DEACTIVATED, we will process any pending births so // that our data structures (which counted the outstanding births) remain // consistent. @@ -512,9 +501,6 @@ const Births* birth, const TrackedTime& time_posted, const TaskStopwatch& stopwatch) { - if (!kTrackAllTaskObjects) - return; // Not compiled in. - // Even if we have been DEACTIVATED, we will process any pending births so // that our data structures (which counted the outstanding births) remain // consistent. @@ -546,9 +532,6 @@ void ThreadData::TallyRunInAScopedRegionIfTracking( const Births* birth, const TaskStopwatch& stopwatch) { - if (!kTrackAllTaskObjects) - return; // Not compiled in. - // Even if we have been DEACTIVATED, we will process any pending births so // that our data structures (which counted the outstanding births) remain // consistent. @@ -567,9 +550,6 @@ void ThreadData::SnapshotAllExecutedTasks( ProcessDataPhaseSnapshot* process_data_phase, BirthCountMap* birth_counts) { - if (!kTrackAllTaskObjects) - return; // Not compiled in. - // Get an unchanging copy of a ThreadData list. ThreadData* my_list = ThreadData::first(); @@ -659,8 +639,6 @@ } bool ThreadData::Initialize() { - if (!kTrackAllTaskObjects) - return false; // Not compiled in. if (status_ >= DEACTIVATED) return true; // Someone else did the initialization. // Due to racy lazy initialization in tests, we'll need to recheck status_ @@ -761,7 +739,7 @@ TrackedTime ThreadData::Now() { if (kAllowAlternateTimeSourceHandling && now_function_) return TrackedTime::FromMilliseconds((*now_function_)()); - if (kTrackAllTaskObjects && IsProfilerTimingEnabled() && TrackingStatus()) + if (IsProfilerTimingEnabled() && TrackingStatus()) return TrackedTime::Now(); return TrackedTime(); // Super fast when disabled, or not compiled. }
diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc index 2803021..2ebef32 100644 --- a/base/win/scoped_handle.cc +++ b/base/win/scoped_handle.cc
@@ -12,6 +12,11 @@ #include "base/logging.h" #include "base/synchronization/lock_impl.h" +extern "C" { +__declspec(dllexport) void* GetHandleVerifier(); +typedef void* (*GetHandleVerifierFn)(); +} + namespace { struct HandleHash { @@ -30,20 +35,9 @@ }; typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; -// g_lock protects g_handle_map and g_closing. +// g_lock protects the handle map and setting g_active_verifier. typedef base::internal::LockImpl NativeLock; base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; -base::LazyInstance<HandleMap>::Leaky g_handle_map = LAZY_INSTANCE_INITIALIZER; -bool g_closing = false; - -// g_verifier_enabled is not protected by g_lock because that would require -// using the lock (hence, synchornizing multiple threads) even when the -// verifier is not in use. Note that this variable is initialized to track all -// handles, and it should only move to the disabled state, and never back to -// enabled, because that would crash when seeing handles created while the -// verifier was disabled. This also implies that it is OK if the value change is -// not propagated immediately to all CPUs (as would happen with a lock). -bool g_verifier_enabled = true; bool CloseHandleWrapper(HANDLE handle) { if (!::CloseHandle(handle)) @@ -68,81 +62,180 @@ DISALLOW_COPY_AND_ASSIGN(AutoNativeLock); }; +// Implements the actual object that is verifying handles for this process. +// The active instance is shared across the module boundary but there is no +// way to delete this object from the wrong side of it (or any side, actually). +class ActiveVerifier { + public: + explicit ActiveVerifier(bool enabled) + : enabled_(enabled), closing_(false), lock_(g_lock.Pointer()) { + } + + // Retrieves the current verifier. + static ActiveVerifier* Get(); + + // The methods required by HandleTraits. They are virtual because we need to + // forward the call execution to another module, instead of letting the + // compiler call the version that is linked in the current module. + virtual bool CloseHandle(HANDLE handle); + virtual void StartTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2); + virtual void StopTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2); + virtual void Disable(); + virtual void OnHandleBeingClosed(HANDLE handle); + + private: + ~ActiveVerifier(); // Not implemented. + + static void InstallVerifier(); + + bool enabled_; + bool closing_; + NativeLock* lock_; + HandleMap map_; + DISALLOW_COPY_AND_ASSIGN(ActiveVerifier); +}; +ActiveVerifier* g_active_verifier = NULL; + +// static +ActiveVerifier* ActiveVerifier::Get() { + if (!g_active_verifier) + ActiveVerifier::InstallVerifier(); + + return g_active_verifier; +} + +// static +void ActiveVerifier::InstallVerifier() { +#if defined(COMPONENT_BUILD) + AutoNativeLock lock(g_lock.Get()); + g_active_verifier = new ActiveVerifier(true); +#else + // If you are reading this, wondering why your process seems deadlocked, take + // a look at your DllMain code and remove things that should not be done + // there, like doing whatever gave you that nice windows handle you are trying + // to store in a ScopedHandle. + HMODULE main_module = ::GetModuleHandle(NULL); + GetHandleVerifierFn get_handle_verifier = + reinterpret_cast<GetHandleVerifierFn>(::GetProcAddress( + main_module, "GetHandleVerifier")); + + if (!get_handle_verifier) { + g_active_verifier = new ActiveVerifier(false); + return; + } + + ActiveVerifier* verifier = + reinterpret_cast<ActiveVerifier*>(get_handle_verifier()); + + // This lock only protects against races in this module, which is fine. + AutoNativeLock lock(g_lock.Get()); + g_active_verifier = verifier ? verifier : new ActiveVerifier(true); +#endif +} + +bool ActiveVerifier::CloseHandle(HANDLE handle) { + if (!enabled_) + return CloseHandleWrapper(handle); + + AutoNativeLock lock(*lock_); + closing_ = true; + CloseHandleWrapper(handle); + closing_ = false; + + return true; +} + +void ActiveVerifier::StartTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2) { + if (!enabled_) + return; + + // Grab the thread id before the lock. + DWORD thread_id = GetCurrentThreadId(); + + AutoNativeLock lock(*lock_); + + Info handle_info = { owner, pc1, pc2, thread_id }; + std::pair<HANDLE, Info> item(handle, handle_info); + std::pair<HandleMap::iterator, bool> result = map_.insert(item); + if (!result.second) { + Info other = result.first->second; + base::debug::Alias(&other); + CHECK(false); + } +} + +void ActiveVerifier::StopTracking(HANDLE handle, const void* owner, + const void* pc1, const void* pc2) { + if (!enabled_) + return; + + AutoNativeLock lock(*lock_); + HandleMap::iterator i = map_.find(handle); + if (i == map_.end()) + CHECK(false); + + Info other = i->second; + if (other.owner != owner) { + base::debug::Alias(&other); + CHECK(false); + } + + map_.erase(i); +} + +void ActiveVerifier::Disable() { + enabled_ = false; +} + +void ActiveVerifier::OnHandleBeingClosed(HANDLE handle) { + AutoNativeLock lock(*lock_); + if (closing_) + return; + + HandleMap::iterator i = map_.find(handle); + if (i == map_.end()) + return; + + Info other = i->second; + base::debug::Alias(&other); + CHECK(false); +} + } // namespace +void* GetHandleVerifier() { + return g_active_verifier; +} + namespace base { namespace win { // Static. bool HandleTraits::CloseHandle(HANDLE handle) { - if (!g_verifier_enabled) - return CloseHandleWrapper(handle); - - AutoNativeLock lock(g_lock.Get()); - g_closing = true; - CloseHandleWrapper(handle); - g_closing = false; - - return true; + return ActiveVerifier::Get()->CloseHandle(handle); } // Static. void VerifierTraits::StartTracking(HANDLE handle, const void* owner, const void* pc1, const void* pc2) { - if (!g_verifier_enabled) - return; - - // Grab the thread id before the lock. - DWORD thread_id = GetCurrentThreadId(); - - AutoNativeLock lock(g_lock.Get()); - - Info handle_info = { owner, pc1, pc2, thread_id }; - std::pair<HANDLE, Info> item(handle, handle_info); - std::pair<HandleMap::iterator, bool> result = g_handle_map.Get().insert(item); - if (!result.second) { - Info other = result.first->second; - debug::Alias(&other); - CHECK(false); - } + return ActiveVerifier::Get()->StartTracking(handle, owner, pc1, pc2); } // Static. void VerifierTraits::StopTracking(HANDLE handle, const void* owner, const void* pc1, const void* pc2) { - if (!g_verifier_enabled) - return; - - AutoNativeLock lock(g_lock.Get()); - HandleMap::iterator i = g_handle_map.Get().find(handle); - if (i == g_handle_map.Get().end()) - CHECK(false); - - Info other = i->second; - if (other.owner != owner) { - debug::Alias(&other); - CHECK(false); - } - - g_handle_map.Get().erase(i); + return ActiveVerifier::Get()->StopTracking(handle, owner, pc1, pc2); } void DisableHandleVerifier() { - g_verifier_enabled = false; + return ActiveVerifier::Get()->Disable(); } void OnHandleBeingClosed(HANDLE handle) { - AutoNativeLock lock(g_lock.Get()); - if (g_closing) - return; - - HandleMap::iterator i = g_handle_map.Get().find(handle); - if (i == g_handle_map.Get().end()) - return; - - Info other = i->second; - debug::Alias(&other); - CHECK(false); + return ActiveVerifier::Get()->OnHandleBeingClosed(handle); } } // namespace win
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py index ad51f03..04972642 100755 --- a/build/android/provision_devices.py +++ b/build/android/provision_devices.py
@@ -42,26 +42,185 @@ HELP_TEXT = '{}s on L, {}s on pre-L'.format(LOLLIPOP, PRE_LOLLIPOP) -def KillHostHeartbeat(): - ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE) - stdout, _ = ps.communicate() - matches = re.findall('\\n.*host_heartbeat.*', stdout) - for match in matches: - logging.info('An instance of host heart beart running... will kill') - pid = re.findall(r'(\S+)', match)[1] - subprocess.call(['kill', str(pid)]) +class _PHASES(object): + WIPE = 'wipe' + PROPERTIES = 'properties' + FINISH = 'finish' + + ALL = [WIPE, PROPERTIES, FINISH] -def LaunchHostHeartbeat(): - # Kill if existing host_heartbeat - KillHostHeartbeat() - # Launch a new host_heartbeat - logging.info('Spawning host heartbeat...') - subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT, - 'build/android/host_heartbeat.py')]) +def ProvisionDevices(options): + if options.device is not None: + devices = [options.device] + else: + devices = android_commands.GetAttachedDevices() + + parallel_devices = device_utils.DeviceUtils.parallel(devices) + parallel_devices.pMap(ProvisionDevice, options) + if options.auto_reconnect: + _LaunchHostHeartbeat() + blacklist = device_blacklist.ReadBlacklist() + if all(d in blacklist for d in devices): + raise device_errors.NoDevicesError + return 0 -def PushAndLaunchAdbReboot(device, target): +def ProvisionDevice(device, options): + if options.reboot_timeout: + reboot_timeout = options.reboot_timeout + elif (device.build_version_sdk >= + constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP): + reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP + else: + reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP + + def should_run_phase(phase_name): + return not options.phases or phase_name in options.phases + + def run_phase(phase_func, reboot=True): + device.WaitUntilFullyBooted(timeout=reboot_timeout) + phase_func(device, options) + if reboot: + device.Reboot(False, retries=0) + device.adb.WaitForDevice() + + if should_run_phase(_PHASES.WIPE): + run_phase(WipeDevice) + + if should_run_phase(_PHASES.PROPERTIES): + run_phase(SetProperties) + + if should_run_phase(_PHASES.FINISH): + run_phase(FinishProvisioning, reboot=False) + + +def WipeDevice(device, options): + """Wipes data from device, keeping only the adb_keys for authorization. + + After wiping data on a device that has been authorized, adb can still + communicate with the device, but after reboot the device will need to be + re-authorized because the adb keys file is stored in /data/misc/adb/. + Thus, adb_keys file is rewritten so the device does not need to be + re-authorized. + + Arguments: + device: the device to wipe + """ + if options.skip_wipe: + return + + device.EnableRoot() + device_authorized = device.FileExists(constants.ADB_KEYS_FILE) + if device_authorized: + adb_keys = device.ReadFile(constants.ADB_KEYS_FILE, + as_root=True).splitlines() + try: + device.RunShellCommand(['wipe', 'data'], + as_root=True, check_return=True, retries=0) + except device_errors.CommandFailedError: + logging.exception('Possible failure while wiping the device. ' + 'Attempting to continue.') + device.adb.WaitForDevice() + + if device_authorized: + adb_keys_set = set(adb_keys) + for adb_key_file in options.adb_key_files or []: + try: + with open(adb_key_file, 'r') as f: + adb_public_keys = f.readlines() + adb_keys_set.update(adb_public_keys) + except IOError: + logging.warning('Unable to find adb keys file %s.' % adb_key_file) + _WriteAdbKeysFile(device, '\n'.join(adb_keys_set)) + + +def _WriteAdbKeysFile(device, adb_keys_string): + dir_path = posixpath.dirname(constants.ADB_KEYS_FILE) + device.RunShellCommand(['mkdir', '-p', dir_path], + as_root=True, check_return=True) + device.RunShellCommand(['restorecon', dir_path], + as_root=True, check_return=True) + device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True) + device.RunShellCommand(['restorecon', constants.ADB_KEYS_FILE], + as_root=True, check_return=True) + + +def SetProperties(device, options): + try: + device.EnableRoot() + except device_errors.CommandFailedError as e: + logging.warning(str(e)) + + _ConfigureLocalProperties(device, options.enable_java_debug) + device_settings.ConfigureContentSettings( + device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) + if options.disable_location: + device_settings.ConfigureContentSettings( + device, device_settings.DISABLE_LOCATION_SETTINGS) + else: + device_settings.ConfigureContentSettings( + device, device_settings.ENABLE_LOCATION_SETTINGS) + device_settings.SetLockScreenSettings(device) + if options.disable_network: + device_settings.ConfigureContentSettings( + device, device_settings.NETWORK_DISABLED_SETTINGS) + + if options.min_battery_level is not None: + try: + battery = battery_utils.BatteryUtils(device) + battery.ChargeDeviceToLevel(options.min_battery_level) + except device_errors.CommandFailedError as e: + logging.exception('Unable to charge device to specified level.') + + +def _ConfigureLocalProperties(device, java_debug=True): + """Set standard readonly testing device properties prior to reboot.""" + local_props = [ + 'persist.sys.usb.config=adb', + 'ro.monkey=1', + 'ro.test_harness=1', + 'ro.audio.silent=1', + 'ro.setupwizard.mode=DISABLED', + ] + if java_debug: + local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY) + local_props.append('debug.checkjni=1') + try: + device.WriteFile( + constants.DEVICE_LOCAL_PROPERTIES_PATH, + '\n'.join(local_props), as_root=True) + # Android will not respect the local props file if it is world writable. + device.RunShellCommand( + ['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH], + as_root=True, check_return=True) + except device_errors.CommandFailedError as e: + logging.warning(str(e)) + + +def FinishProvisioning(device, options): + try: + device.RunShellCommand( + ['date', '-s', time.strftime('%Y%m%d.%H%M%S', time.gmtime())], + as_root=True, check_return=True) + props = device.RunShellCommand('getprop', check_return=True) + for prop in props: + logging.info(' %s' % prop) + if options.auto_reconnect: + _PushAndLaunchAdbReboot(device, options.target) + except (errors.WaitForResponseTimedOutError, + device_errors.CommandTimeoutError): + logging.info('Timed out waiting for device %s. Adding to blacklist.', + str(device)) + # Device black list is reset by bb_device_status_check.py per build. + device_blacklist.ExtendBlacklist([str(device)]) + except device_errors.CommandFailedError: + logging.exception('Failed to provision device %s. Adding to blacklist.', + str(device)) + device_blacklist.ExtendBlacklist([str(device)]) + + +def _PushAndLaunchAdbReboot(device, target): """Pushes and launches the adb_reboot binary on the device. Arguments: @@ -87,163 +246,31 @@ device.PushChangedFiles([(adb_reboot, '/data/local/tmp/')]) # Launch adb_reboot logging.info(' Launching adb_reboot ...') - device.RunShellCommand([ - device.GetDevicePieWrapper(), - '/data/local/tmp/adb_reboot']) + device.RunShellCommand( + [device.GetDevicePieWrapper(), '/data/local/tmp/adb_reboot'], + check_return=True) -def _ConfigureLocalProperties(device, java_debug=True): - """Set standard readonly testing device properties prior to reboot.""" - local_props = [ - 'persist.sys.usb.config=adb', - 'ro.monkey=1', - 'ro.test_harness=1', - 'ro.audio.silent=1', - 'ro.setupwizard.mode=DISABLED', - ] - if java_debug: - local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY) - local_props.append('debug.checkjni=1') - try: - device.WriteFile( - constants.DEVICE_LOCAL_PROPERTIES_PATH, - '\n'.join(local_props), as_root=True) - # Android will not respect the local props file if it is world writable. - device.RunShellCommand( - ['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH], - as_root=True) - except device_errors.CommandFailedError as e: - logging.warning(str(e)) - - # LOCAL_PROPERTIES_PATH = '/data/local.prop' - -def WriteAdbKeysFile(device, adb_keys_string): - dir_path = posixpath.dirname(constants.ADB_KEYS_FILE) - device.RunShellCommand('mkdir -p %s' % dir_path, as_root=True) - device.RunShellCommand('restorecon %s' % dir_path, as_root=True) - device.WriteFile(constants.ADB_KEYS_FILE, adb_keys_string, as_root=True) - device.RunShellCommand('restorecon %s' % constants.ADB_KEYS_FILE, - as_root=True) +def _LaunchHostHeartbeat(): + # Kill if existing host_heartbeat + _KillHostHeartbeat() + # Launch a new host_heartbeat + logging.info('Spawning host heartbeat...') + subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT, + 'build/android/host_heartbeat.py')]) -def WipeDeviceData(device, options): - """Wipes data from device, keeping only the adb_keys for authorization. - - After wiping data on a device that has been authorized, adb can still - communicate with the device, but after reboot the device will need to be - re-authorized because the adb keys file is stored in /data/misc/adb/. - Thus, adb_keys file is rewritten so the device does not need to be - re-authorized. - - Arguments: - device: the device to wipe - """ - device_authorized = device.FileExists(constants.ADB_KEYS_FILE) - if device_authorized: - adb_keys = device.ReadFile(constants.ADB_KEYS_FILE, - as_root=True).splitlines() - device.RunShellCommand('wipe data', as_root=True) - if device_authorized: - adb_keys_set = set(adb_keys) - for adb_key_file in options.adb_key_files or []: - try: - with open(adb_key_file, 'r') as f: - adb_public_keys = f.readlines() - adb_keys_set.update(adb_public_keys) - except IOError: - logging.warning('Unable to find adb keys file %s.' % adb_key_file) - WriteAdbKeysFile(device, '\n'.join(adb_keys_set)) - - -def WipeDeviceIfPossible(device, timeout, options): - try: - device.EnableRoot() - WipeDeviceData(device, options) - device.Reboot(True, timeout=timeout, retries=0) - except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError): - pass - - -def ProvisionDevice(device, options): - if options.reboot_timeout: - reboot_timeout = options.reboot_timeout - elif (device.build_version_sdk >= - constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP): - reboot_timeout = _DEFAULT_TIMEOUTS.LOLLIPOP - else: - reboot_timeout = _DEFAULT_TIMEOUTS.PRE_LOLLIPOP - - try: - if not options.skip_wipe: - WipeDeviceIfPossible(device, reboot_timeout, options) - try: - device.EnableRoot() - except device_errors.CommandFailedError as e: - logging.warning(str(e)) - _ConfigureLocalProperties(device, options.enable_java_debug) - device_settings.ConfigureContentSettings( - device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) - if options.disable_location: - device_settings.ConfigureContentSettings( - device, device_settings.DISABLE_LOCATION_SETTINGS) - else: - device_settings.ConfigureContentSettings( - device, device_settings.ENABLE_LOCATION_SETTINGS) - device_settings.SetLockScreenSettings(device) - if options.disable_network: - device_settings.ConfigureContentSettings( - device, device_settings.NETWORK_DISABLED_SETTINGS) - if options.min_battery_level is not None: - try: - battery = battery_utils.BatteryUtils(device) - battery.ChargeDeviceToLevel(options.min_battery_level) - except device_errors.CommandFailedError as e: - logging.exception('Unable to charge device to specified level.') - - if not options.skip_wipe: - device.Reboot(True, timeout=reboot_timeout, retries=0) - device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S', - time.gmtime()), - as_root=True) - props = device.RunShellCommand('getprop') - for prop in props: - logging.info(' %s' % prop) - if options.auto_reconnect: - PushAndLaunchAdbReboot(device, options.target) - except (errors.WaitForResponseTimedOutError, - device_errors.CommandTimeoutError): - logging.info('Timed out waiting for device %s. Adding to blacklist.', - str(device)) - # Device black list is reset by bb_device_status_check.py per build. - device_blacklist.ExtendBlacklist([str(device)]) - except device_errors.CommandFailedError: - logging.exception('Failed to provision device %s. Adding to blacklist.', - str(device)) - device_blacklist.ExtendBlacklist([str(device)]) - - -def ProvisionDevices(options): - if options.device is not None: - devices = [options.device] - else: - devices = android_commands.GetAttachedDevices() - - parallel_devices = device_utils.DeviceUtils.parallel(devices) - parallel_devices.pMap(ProvisionDevice, options) - if options.auto_reconnect: - LaunchHostHeartbeat() - blacklist = device_blacklist.ReadBlacklist() - if all(d in blacklist for d in devices): - raise device_errors.NoDevicesError - return 0 +def _KillHostHeartbeat(): + ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE) + stdout, _ = ps.communicate() + matches = re.findall('\\n.*host_heartbeat.*', stdout) + for match in matches: + logging.info('An instance of host heart beart running... will kill') + pid = re.findall(r'(\S+)', match)[1] + subprocess.call(['kill', str(pid)]) def main(): - custom_handler = logging.StreamHandler(sys.stdout) - custom_handler.setFormatter(run_tests_helper.CustomFormatter()) - logging.getLogger().addHandler(custom_handler) - logging.getLogger().setLevel(logging.INFO) - # Recommended options on perf bots: # --disable-network # TODO(tonyg): We eventually want network on. However, currently radios @@ -258,6 +285,10 @@ parser.add_argument('-d', '--device', metavar='SERIAL', help='the serial number of the device to be provisioned' ' (the default is to provision all devices attached)') + parser.add_argument('--phase', action='append', choices=_PHASES.ALL, + dest='phases', + help='Phases of provisioning to run. ' + '(If omitted, all phases will be run.)') parser.add_argument('--skip-wipe', action='store_true', default=False, help="don't wipe device data during provisioning") parser.add_argument('--reboot-timeout', metavar='SECS', type=int, @@ -281,9 +312,13 @@ ' disconnections') parser.add_argument('--adb-key-files', type=str, nargs='+', help='list of adb keys to push to device') + parser.add_argument('-v', '--verbose', action='count', default=1, + help='Log more information.') args = parser.parse_args() constants.SetBuildType(args.target) + run_tests_helper.SetLogLevel(args.verbose) + return ProvisionDevices(args)
diff --git a/build/android/pylib/device/battery_utils.py b/build/android/pylib/device/battery_utils.py index cca89c7..227e902 100644 --- a/build/android/pylib/device/battery_utils.py +++ b/build/android/pylib/device/battery_utils.py
@@ -233,12 +233,17 @@ Raises: device_errors.CommandFailedError: When resetting batterystats fails to reset power values. + device_errors.DeviceVersionError: If device is not L or higher. """ def battery_updates_disabled(): return self.GetCharging() is False + if (self._device.build_version_sdk < + constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP): + raise device_errors.DeviceVersionError('Device must be L or higher.') + self._device.RunShellCommand( - ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True) + ['dumpsys', 'battery', 'reset'], check_return=True) self._device.RunShellCommand( ['dumpsys', 'batterystats', '--reset'], check_return=True) battery_data = self._device.RunShellCommand( @@ -252,6 +257,8 @@ and l[PWI_POWER_INDEX] != 0): raise device_errors.CommandFailedError( 'Non-zero pmi value found after reset.') + self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'ac', '0'], + check_return=True) self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True) timeout_retry.WaitFor(battery_updates_disabled, wait_period=1) @@ -263,12 +270,17 @@ Args: timeout: timeout in seconds retries: number of retries + + Raises: + device_errors.DeviceVersionError: If device is not L or higher. """ def battery_updates_enabled(): return self.GetCharging() is True - self._device.RunShellCommand(['dumpsys', 'battery', 'set', 'usb', '1'], - check_return=True) + if (self._device.build_version_sdk < + constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP): + raise device_errors.DeviceVersionError('Device must be L or higher.') + self._device.RunShellCommand(['dumpsys', 'battery', 'reset'], check_return=True) timeout_retry.WaitFor(battery_updates_enabled, wait_period=1) @@ -294,7 +306,7 @@ retries: number of retries Raises: - device_errors.CommandFailedError: If device is not L or higher. + device_errors.DeviceVersionError: If device is not L or higher. """ if (self._device.build_version_sdk < constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP):
diff --git a/build/android/pylib/device/battery_utils_test.py b/build/android/pylib/device/battery_utils_test.py index 03ea196..2135ac0 100755 --- a/build/android/pylib/device/battery_utils_test.py +++ b/build/android/pylib/device/battery_utils_test.py
@@ -95,18 +95,18 @@ mock.ANY, retries=0, single_line=True, timeout=10, check_return=True), '22'), (self.call.device.RunShellCommand( - ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True), []), + ['dumpsys', 'battery', 'reset'], check_return=True), []), (self.call.device.RunShellCommand( ['dumpsys', 'batterystats', '--reset'], check_return=True), []), (self.call.device.RunShellCommand( ['dumpsys', 'batterystats', '--charged', '--checkin'], check_return=True), []), (self.call.device.RunShellCommand( + ['dumpsys', 'battery', 'set', 'ac', '0'], check_return=True), []), + (self.call.device.RunShellCommand( ['dumpsys', 'battery', 'set', 'usb', '0'], check_return=True), []), (self.call.battery.GetCharging(), False), (self.call.device.RunShellCommand( - ['dumpsys', 'battery', 'set', 'usb', '1'], check_return=True), []), - (self.call.device.RunShellCommand( ['dumpsys', 'battery', 'reset'], check_return=True), []), (self.call.battery.GetCharging(), True)): with self.battery.BatteryMeasurement():
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py index 8025b0f..90d5ca0 100644 --- a/build/android/pylib/utils/isolator.py +++ b/build/android/pylib/utils/isolator.py
@@ -24,12 +24,15 @@ def DefaultConfigVariables(): + # Note: This list must match the --config-vars in build/isolate.gypi return { 'CONFIGURATION_NAME': constants.GetBuildType(), 'OS': 'android', 'asan': '0', + 'branding': 'Chromium', 'chromeos': '0', 'component': 'static_library', + 'enable_pepper_cdms': '0', 'enable_plugins': '0', 'fastbuild': '0', 'icu_use_data_file_flag': '1',
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 87f4cec..b1bd6e7 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -775,6 +775,9 @@ test_type='JUnit', test_package=args.test_suite) + if args.json_results_file: + json_results.GenerateJsonResultsFile(results, args.json_results_file) + return exit_code
diff --git a/build/common.gypi b/build/common.gypi index faa31f2..e80d6055 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -1022,8 +1022,8 @@ 'optimize_jni_generation%': 0, }], - # TODO(rmcilroy): Remove ios check. http://crbug.com/421063. - ['OS!="ios"', { + # TODO(rmcilroy): Remove ios/chromecast checks. http://crbug.com/421063. + ['OS!="ios" and chromecast==0', { 'v8_use_external_startup_data%': 1, }, { 'v8_use_external_startup_data%': 0,
diff --git a/build/isolate.gypi b/build/isolate.gypi index c85585dc..7b050e2c 100644 --- a/build/isolate.gypi +++ b/build/isolate.gypi
@@ -61,9 +61,6 @@ # Variables should use the -V FOO=<(FOO) form so frequent values, # like '0' or '1', aren't stripped out by GYP. Run 'isolate.py help' for # more details. - # - # This list needs to be kept in sync with the cmd line options - # in src/build/android/pylib/gtest/setup.py. # Path variables are used to replace file paths when loading a .isolate # file @@ -74,12 +71,16 @@ # the .isolate file but are not considered relative paths. '--extra-variable', 'version_full=<(version_full)', + # Note: This list must match DefaultConfigVariables() + # in build/android/pylib/utils/isolator.py '--config-variable', 'CONFIGURATION_NAME=<(CONFIGURATION_NAME)', '--config-variable', 'OS=<(OS)', '--config-variable', 'asan=<(asan)', + '--config-variable', 'branding=<(branding)', '--config-variable', 'chromeos=<(chromeos)', '--config-variable', 'component=<(component)', '--config-variable', 'disable_nacl=<(disable_nacl)', + '--config-variable', 'enable_pepper_cdms=<(enable_pepper_cdms)', '--config-variable', 'enable_plugins=<(enable_plugins)', '--config-variable', 'fastbuild=<(fastbuild)', '--config-variable', 'icu_use_data_file_flag=<(icu_use_data_file_flag)',
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc index 33090fb9..6668c1e 100644 --- a/build/sanitizers/sanitizer_options.cc +++ b/build/sanitizers/sanitizer_options.cc
@@ -66,8 +66,6 @@ // so the slow unwinder may not work properly. // detect_stack_use_after_return=1 - use fake stack to delay the reuse of // stack allocations and detect stack-use-after-return errors. -// detect_container_overflow=0 - do not detect overflows in containers -// until crbug.com/459632 is fixed. #if defined(OS_LINUX) #if defined(GOOGLE_CHROME_BUILD) // Default AddressSanitizer options for the official build. These do not affect @@ -76,22 +74,20 @@ const char kAsanDefaultOptions[] = "legacy_pthread_cond=1 malloc_context_size=5 strict_memcmp=0 " "symbolize=false check_printf=1 use_sigaltstack=1 detect_leaks=0 " - "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 " - "detect_container_overflow=0 "; + "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1"; #else // Default AddressSanitizer options for buildbots and non-official builds. const char *kAsanDefaultOptions = "strict_memcmp=0 symbolize=false check_printf=1 use_sigaltstack=1 " "detect_leaks=0 strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 " - "detect_stack_use_after_return=1 detect_container_overflow=0 "; + "detect_stack_use_after_return=1 "; #endif // GOOGLE_CHROME_BUILD #elif defined(OS_MACOSX) const char *kAsanDefaultOptions = "strict_memcmp=0 replace_intrin=0 check_printf=1 use_sigaltstack=1 " "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 " - "detect_stack_use_after_return=1 detect_odr_violation=0 " - "detect_container_overflow=0 "; + "detect_stack_use_after_return=1 detect_odr_violation=0 "; static const char kNaClDefaultOptions[] = "handle_segv=0"; static const char kNaClFlag[] = "--type=nacl-loader"; #endif // OS_LINUX
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index bc055806..539ea6f0 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -239,9 +239,6 @@ // http://crbug.com/363999 "race:v8::internal::EnterDebugger::*EnterDebugger\n" -// http://crbug.com/364006 -"race:gfx::ImageFamily::~ImageFamily\n" - // https://code.google.com/p/v8/issues/detail?id=3143 "race:v8::internal::FLAG_track_double_fields\n"
diff --git a/cc/layers/content_layer.cc b/cc/layers/content_layer.cc index d1ff842..7efa1c2 100644 --- a/cc/layers/content_layer.cc +++ b/cc/layers/content_layer.cc
@@ -125,7 +125,8 @@ SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0); client_->PaintContents(canvas, gfx::Rect(width, height), ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); return picture; }
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc index 0da4213..dfbb826 100644 --- a/cc/layers/delegated_renderer_layer_impl.cc +++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -474,6 +474,9 @@ DrawQuad* output_quad = render_pass->CopyFromAndAppendDrawQuad( delegated_quad, output_shared_quad_state); output_quad->visible_rect = quad_visible_rect; + // TODO(danakj): crbug.com/455931 + output_quad->IterateResources(base::Bind( + &ValidateResource, layer_tree_impl()->resource_provider())); } else { RenderPassId delegated_contributing_render_pass_id = RenderPassDrawQuad::MaterialCast(delegated_quad)->render_pass_id; @@ -494,12 +497,12 @@ output_shared_quad_state, output_contributing_render_pass_id); output_quad->visible_rect = quad_visible_rect; + + // TODO(danakj): crbug.com/455931 + output_quad->IterateResources(base::Bind( + &ValidateResource, layer_tree_impl()->resource_provider())); } } - - // TODO(danakj): crbug.com/455931 - render_pass->quad_list.back()->IterateResources( - base::Bind(&ValidateResource, layer_tree_impl()->resource_provider())); } }
diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc index 6886612..b972ec19 100644 --- a/cc/layers/picture_image_layer.cc +++ b/cc/layers/picture_image_layer.cc
@@ -72,7 +72,8 @@ SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(clip)); PaintContents(canvas, clip, painting_control); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); display_item_list->AppendItem(DrawingDisplayItem::Create(picture)); return display_item_list; }
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index d41b5415..5c4cb06 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc
@@ -205,7 +205,8 @@ SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0); client_->PaintContents(canvas, gfx::Rect(width, height), ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); return picture; }
diff --git a/cc/resources/display_item_list.cc b/cc/resources/display_item_list.cc index 26ff003..33990d0 100644 --- a/cc/resources/display_item_list.cc +++ b/cc/resources/display_item_list.cc
@@ -72,7 +72,7 @@ canvas->clipRect(gfx::RectToSkRect(layer_rect_)); for (size_t i = 0; i < items_.size(); ++i) items_[i]->Raster(canvas.get(), NULL); - picture_ = skia::AdoptRef(recorder.endRecording()); + picture_ = skia::AdoptRef(recorder.endRecordingAsPicture()); DCHECK(picture_); } @@ -127,7 +127,8 @@ canvas->clipRect(gfx::RectToSkRect(layer_rect_)); for (size_t i = 0; i < items_.size(); ++i) items_[i]->RasterForTracing(canvas); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); std::string b64_picture; PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture);
diff --git a/cc/resources/display_item_list_unittest.cc b/cc/resources/display_item_list_unittest.cc index c9b9558..898b5fe 100644 --- a/cc/resources/display_item_list_unittest.cc +++ b/cc/resources/display_item_list_unittest.cc
@@ -44,7 +44,7 @@ canvas->translate(offset.x(), offset.y()); canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint); canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); DrawDisplayList(pixels, layer_rect, list); @@ -83,7 +83,7 @@ recorder.beginRecording(gfx::RectFToSkRect(first_recording_rect))); canvas->translate(first_offset.x(), first_offset.y()); canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); gfx::Rect clip_rect(60, 60, 10, 10); @@ -95,7 +95,7 @@ recorder.beginRecording(gfx::RectFToSkRect(second_recording_rect))); canvas->translate(second_offset.x(), second_offset.y()); canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); list->AppendItem(EndClipDisplayItem::Create()); @@ -138,7 +138,7 @@ recorder.beginRecording(gfx::RectFToSkRect(first_recording_rect))); canvas->translate(first_offset.x(), first_offset.y()); canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); gfx::Transform transform; @@ -151,7 +151,7 @@ recorder.beginRecording(gfx::RectFToSkRect(second_recording_rect))); canvas->translate(second_offset.x(), second_offset.y()); canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); list->AppendItem(EndTransformDisplayItem::Create());
diff --git a/cc/resources/display_list_raster_source.cc b/cc/resources/display_list_raster_source.cc index 9a0bc911..e3542b4d 100644 --- a/cc/resources/display_list_raster_source.cc +++ b/cc/resources/display_list_raster_source.cc
@@ -130,7 +130,8 @@ display_list_rect.height()); if (!display_list_rect.IsEmpty()) PlaybackToCanvas(canvas, display_list_rect, 1.0); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); return picture; }
diff --git a/cc/resources/gpu_rasterizer.cc b/cc/resources/gpu_rasterizer.cc index 1620c2b..a1d33bc 100644 --- a/cc/resources/gpu_rasterizer.cc +++ b/cc/resources/gpu_rasterizer.cc
@@ -52,7 +52,8 @@ canvas->save(); raster_source->PlaybackToCanvas(canvas.get(), rect, scale); canvas->restore(); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); // Turn on distance fields for layers that have ever animated. bool use_distance_field_text =
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc index e88ff21..9375d7e 100644 --- a/cc/resources/picture.cc +++ b/cc/resources/picture.cc
@@ -218,7 +218,7 @@ painter->PaintContents(canvas.get(), layer_rect_, painting_control); canvas->restore(); - picture_ = skia::AdoptRef(recorder.endRecording()); + picture_ = skia::AdoptRef(recorder.endRecordingAsPicture()); DCHECK(picture_); EmitTraceSnapshot();
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h index c05185a..34e7def 100644 --- a/cc/resources/picture_layer_tiling.h +++ b/cc/resources/picture_layer_tiling.h
@@ -91,6 +91,7 @@ gfx::Rect live_tiles_rect() const { return live_tiles_rect_; } gfx::Size tile_size() const { return tiling_data_.max_texture_size(); } float contents_scale() const { return contents_scale_; } + const TilingData* tiling_data() const { return &tiling_data_; } Tile* TileAt(int i, int j) const { TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j));
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h index d4d55a3e..cf95935 100644 --- a/cc/resources/picture_layer_tiling_set.h +++ b/cc/resources/picture_layer_tiling_set.h
@@ -31,10 +31,10 @@ LOWER_THAN_LOW_RES }; struct TilingRange { - TilingRange(size_t start, size_t end) : start(start), end(end) {} + TilingRange(int start, int end) : start(start), end(end) {} - size_t start; - size_t end; + int start; + int end; }; static scoped_ptr<PictureLayerTilingSet> Create(
diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc index 2eceb71..7c68611 100644 --- a/cc/resources/picture_layer_tiling_set_unittest.cc +++ b/cc/resources/picture_layer_tiling_set_unittest.cc
@@ -86,26 +86,26 @@ higher_than_high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0u, higher_than_high_res_range.start); - EXPECT_EQ(1u, higher_than_high_res_range.end); + EXPECT_EQ(0, higher_than_high_res_range.start); + EXPECT_EQ(1, higher_than_high_res_range.end); high_res_range = set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(1u, high_res_range.start); - EXPECT_EQ(2u, high_res_range.end); + EXPECT_EQ(1, high_res_range.start); + EXPECT_EQ(2, high_res_range.end); between_high_and_low_res_range = set->GetTilingRange(PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(2u, between_high_and_low_res_range.start); - EXPECT_EQ(3u, between_high_and_low_res_range.end); + EXPECT_EQ(2, between_high_and_low_res_range.start); + EXPECT_EQ(3, between_high_and_low_res_range.end); low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(3u, low_res_range.start); - EXPECT_EQ(4u, low_res_range.end); + EXPECT_EQ(3, low_res_range.start); + EXPECT_EQ(4, low_res_range.end); lower_than_low_res_range = set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(4u, lower_than_low_res_range.start); - EXPECT_EQ(5u, lower_than_low_res_range.end); + EXPECT_EQ(4, lower_than_low_res_range.start); + EXPECT_EQ(5, lower_than_low_res_range.end); scoped_ptr<PictureLayerTilingSet> set_without_low_res = CreateTilingSet(&client); @@ -117,26 +117,26 @@ higher_than_high_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0u, higher_than_high_res_range.start); - EXPECT_EQ(1u, higher_than_high_res_range.end); + EXPECT_EQ(0, higher_than_high_res_range.start); + EXPECT_EQ(1, higher_than_high_res_range.end); high_res_range = set_without_low_res->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(1u, high_res_range.start); - EXPECT_EQ(2u, high_res_range.end); + EXPECT_EQ(1, high_res_range.start); + EXPECT_EQ(2, high_res_range.end); between_high_and_low_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(2u, between_high_and_low_res_range.start); - EXPECT_EQ(4u, between_high_and_low_res_range.end); + EXPECT_EQ(2, between_high_and_low_res_range.start); + EXPECT_EQ(4, between_high_and_low_res_range.end); low_res_range = set_without_low_res->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(0u, low_res_range.end - low_res_range.start); + EXPECT_EQ(0, low_res_range.end - low_res_range.start); lower_than_low_res_range = set_without_low_res->GetTilingRange( PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); + EXPECT_EQ(0, lower_than_low_res_range.end - lower_than_low_res_range.start); scoped_ptr<PictureLayerTilingSet> set_with_only_high_and_low_res = CreateTilingSet(&client); @@ -147,28 +147,28 @@ higher_than_high_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0u, + EXPECT_EQ(0, higher_than_high_res_range.end - higher_than_high_res_range.start); high_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(0u, high_res_range.start); - EXPECT_EQ(1u, high_res_range.end); + EXPECT_EQ(0, high_res_range.start); + EXPECT_EQ(1, high_res_range.end); between_high_and_low_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(0u, between_high_and_low_res_range.end - - between_high_and_low_res_range.start); + EXPECT_EQ(0, between_high_and_low_res_range.end - + between_high_and_low_res_range.start); low_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(1u, low_res_range.start); - EXPECT_EQ(2u, low_res_range.end); + EXPECT_EQ(1, low_res_range.start); + EXPECT_EQ(2, low_res_range.end); lower_than_low_res_range = set_with_only_high_and_low_res->GetTilingRange( PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); + EXPECT_EQ(0, lower_than_low_res_range.end - lower_than_low_res_range.start); scoped_ptr<PictureLayerTilingSet> set_with_only_high_res = CreateTilingSet(&client); @@ -177,26 +177,26 @@ higher_than_high_res_range = set_with_only_high_res->GetTilingRange( PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); - EXPECT_EQ(0u, + EXPECT_EQ(0, higher_than_high_res_range.end - higher_than_high_res_range.start); high_res_range = set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::HIGH_RES); - EXPECT_EQ(0u, high_res_range.start); - EXPECT_EQ(1u, high_res_range.end); + EXPECT_EQ(0, high_res_range.start); + EXPECT_EQ(1, high_res_range.end); between_high_and_low_res_range = set_with_only_high_res->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); - EXPECT_EQ(0u, between_high_and_low_res_range.end - - between_high_and_low_res_range.start); + EXPECT_EQ(0, between_high_and_low_res_range.end - + between_high_and_low_res_range.start); low_res_range = set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(0u, low_res_range.end - low_res_range.start); + EXPECT_EQ(0, low_res_range.end - low_res_range.start); lower_than_low_res_range = set_with_only_high_res->GetTilingRange( PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); + EXPECT_EQ(0, lower_than_low_res_range.end - lower_than_low_res_range.start); } class PictureLayerTilingSetTestWithResources : public testing::Test {
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index be05358..d1fba063 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc
@@ -257,7 +257,8 @@ recorder.beginRecording(tiling_rect.width(), tiling_rect.height()); if (!tiling_rect.IsEmpty()) PlaybackToCanvas(canvas, tiling_rect, 1.0); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); return picture; }
diff --git a/cc/resources/skpicture_content_layer_updater.cc b/cc/resources/skpicture_content_layer_updater.cc index ace97a4..c54f5dca 100644 --- a/cc/resources/skpicture_content_layer_updater.cc +++ b/cc/resources/skpicture_content_layer_updater.cc
@@ -38,7 +38,7 @@ paint_rect, contents_width_scale, contents_height_scale); - picture_ = skia::AdoptRef(recorder.endRecording()); + picture_ = skia::AdoptRef(recorder.endRecordingAsPicture()); } void SkPictureContentLayerUpdater::DrawPicture(SkCanvas* canvas) {
diff --git a/cc/resources/tiling_set_eviction_queue.cc b/cc/resources/tiling_set_eviction_queue.cc index 5ee678b..43d085b6 100644 --- a/cc/resources/tiling_set_eviction_queue.cc +++ b/cc/resources/tiling_set_eviction_queue.cc
@@ -38,285 +38,432 @@ TilingSetEvictionQueue::TilingSetEvictionQueue( PictureLayerTilingSet* tiling_set, bool skip_shared_out_of_order_tiles) - : tiling_set_(tiling_set), - tree_(tiling_set->client()->GetTree()), + : tree_(tiling_set->client()->GetTree()), skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles), - processing_soon_border_rect_(false), - processing_required_for_activation_tiles_(false), - current_priority_bin_(TilePriority::EVENTUALLY), - current_tiling_index_(0u), - current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES), - current_eviction_tile_(nullptr) { + phase_(EVENTUALLY_RECT), + current_tile_(nullptr) { // Early out if the layer has no tilings. - if (!tiling_set_->num_tilings()) + if (!tiling_set->num_tilings()) return; - - current_tiling_index_ = CurrentTilingRange().start - 1u; - AdvanceToNextValidTiling(); + GenerateTilingOrder(tiling_set); + eventually_iterator_ = EventuallyTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_); + if (eventually_iterator_.done()) { + AdvancePhase(); + return; + } + current_tile_ = *eventually_iterator_; } TilingSetEvictionQueue::~TilingSetEvictionQueue() { } -bool TilingSetEvictionQueue::IsEmpty() const { - return !current_eviction_tile_; +void TilingSetEvictionQueue::GenerateTilingOrder( + PictureLayerTilingSet* tiling_set) { + tilings_.reserve(tiling_set->num_tilings()); + // Generate all of the tilings in the order described in the header comment + // for this class. + auto range = + tiling_set->GetTilingRange(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES); + for (int i = range.start; i < range.end; ++i) + tilings_.push_back(tiling_set->tiling_at(i)); + + range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); + for (int i = range.end - 1; i >= range.start; --i) + tilings_.push_back(tiling_set->tiling_at(i)); + + range = tiling_set->GetTilingRange( + PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); + for (int i = range.end - 1; i >= range.start; --i) + tilings_.push_back(tiling_set->tiling_at(i)); + + range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOW_RES); + for (int i = range.start; i < range.end; ++i) + tilings_.push_back(tiling_set->tiling_at(i)); + + range = tiling_set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); + for (int i = range.start; i < range.end; ++i) + tilings_.push_back(tiling_set->tiling_at(i)); + DCHECK_EQ(tiling_set->num_tilings(), tilings_.size()); } -void TilingSetEvictionQueue::Pop() { - DCHECK(!IsEmpty()); +void TilingSetEvictionQueue::AdvancePhase() { + current_tile_ = nullptr; + while (!current_tile_ && + phase_ != VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED) { + phase_ = static_cast<Phase>(phase_ + 1); + switch (phase_) { + case EVENTUALLY_RECT: + NOTREACHED(); + break; + case SOON_BORDER_RECT: + soon_iterator_ = SoonBorderTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_); + if (!soon_iterator_.done()) + current_tile_ = *soon_iterator_; + break; + case SKEWPORT_RECT: + skewport_iterator_ = SkewportTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_); + if (!skewport_iterator_.done()) + current_tile_ = *skewport_iterator_; + break; + case VISIBLE_RECT_OCCLUDED: + visible_iterator_ = VisibleTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_, + true /* return occluded tiles */, + false /* return required for activation tiles */); + if (!visible_iterator_.done()) + current_tile_ = *visible_iterator_; + break; + case VISIBLE_RECT_UNOCCLUDED: + visible_iterator_ = VisibleTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_, + false /* return occluded tiles */, + false /* return required for activation tiles */); + if (!visible_iterator_.done()) + current_tile_ = *visible_iterator_; + break; + case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED: + visible_iterator_ = VisibleTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_, + true /* return occluded tiles */, + true /* return required for activation tiles */); + if (!visible_iterator_.done()) + current_tile_ = *visible_iterator_; + break; + case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED: + visible_iterator_ = VisibleTilingIterator( + &tilings_, tree_, skip_shared_out_of_order_tiles_, + false /* return occluded tiles */, + true /* return required for activation tiles */); + if (!visible_iterator_.done()) + current_tile_ = *visible_iterator_; + break; + } + } +} - if (!AdvanceToNextEvictionTile()) - AdvanceToNextValidTiling(); +bool TilingSetEvictionQueue::IsEmpty() const { + return !current_tile_; } Tile* TilingSetEvictionQueue::Top() { DCHECK(!IsEmpty()); - return current_eviction_tile_; + return current_tile_; } const Tile* TilingSetEvictionQueue::Top() const { DCHECK(!IsEmpty()); - return current_eviction_tile_; + return current_tile_; } -bool TilingSetEvictionQueue::AdvanceToNextEvictionTile() { - // Advance to the next eviction tile within the current priority bin and - // tiling. This is done while advancing to a new tiling and while popping - // the current tile. +void TilingSetEvictionQueue::Pop() { + DCHECK(!IsEmpty()); + current_tile_ = nullptr; + switch (phase_) { + case EVENTUALLY_RECT: + ++eventually_iterator_; + if (!eventually_iterator_.done()) + current_tile_ = *eventually_iterator_; + break; + case SOON_BORDER_RECT: + ++soon_iterator_; + if (!soon_iterator_.done()) + current_tile_ = *soon_iterator_; + break; + case SKEWPORT_RECT: + ++skewport_iterator_; + if (!skewport_iterator_.done()) + current_tile_ = *skewport_iterator_; + break; + case VISIBLE_RECT_OCCLUDED: + case VISIBLE_RECT_UNOCCLUDED: + case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED: + case VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED: + ++visible_iterator_; + if (!visible_iterator_.done()) + current_tile_ = *visible_iterator_; + break; + } + if (!current_tile_) + AdvancePhase(); +} - bool required_for_activation = processing_required_for_activation_tiles_; +// EvictionRectIterator +TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator() + : tile_(nullptr), + tilings_(nullptr), + tree_(ACTIVE_TREE), + skip_shared_out_of_order_tiles_(false), + tiling_index_(0) { +} - for (;;) { - while (spiral_iterator_) { - std::pair<int, int> next_index = spiral_iterator_.index(); - Tile* tile = current_tiling_->TileAt(next_index.first, next_index.second); - ++spiral_iterator_; - if (!tile || !tile->HasResource()) - continue; - current_tiling_->UpdateTileAndTwinPriority(tile); - if (skip_shared_out_of_order_tiles_ && - IsSharedOutOfOrderTile(tree_, tile)) - continue; - DCHECK_EQ(tile->required_for_activation(), required_for_activation); - current_eviction_tile_ = tile; - return true; +TilingSetEvictionQueue::EvictionRectIterator::EvictionRectIterator( + std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles) + : tile_(nullptr), + tilings_(tilings), + tree_(tree), + skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles), + tiling_index_(0) { +} + +template <typename TilingIteratorType> +bool TilingSetEvictionQueue::EvictionRectIterator::AdvanceToNextTile( + TilingIteratorType* iterator) { + bool found_tile = false; + while (!found_tile) { + ++(*iterator); + if (!(*iterator)) { + tile_ = nullptr; + break; } - if (processing_soon_border_rect_) { - // Advance from soon border rect to skewport rect. - processing_soon_border_rect_ = false; - if (current_tiling_->has_skewport_rect_tiles_) { - spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( - ¤t_tiling_->tiling_data_, - current_tiling_->current_skewport_rect_, - current_tiling_->current_visible_rect_, - current_tiling_->current_visible_rect_); - continue; - } + found_tile = GetFirstTileAndCheckIfValid(iterator); + } + return found_tile; +} + +template <typename TilingIteratorType> +bool TilingSetEvictionQueue::EvictionRectIterator::GetFirstTileAndCheckIfValid( + TilingIteratorType* iterator) { + tile_ = (*tilings_)[tiling_index_]->TileAt(iterator->index_x(), + iterator->index_y()); + // If there's nothing to evict, return false. + if (!tile_ || !tile_->HasResource()) + return false; + (*tilings_)[tiling_index_]->UpdateTileAndTwinPriority(tile_); + // If the tile is out of order, return false. + if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tree_, tile_)) + return false; + // In other cases, the tile we got is a viable candidate, return true. + return true; +} + +// EventuallyTilingIterator +TilingSetEvictionQueue::EventuallyTilingIterator::EventuallyTilingIterator( + std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles) + : EvictionRectIterator(tilings, tree, skip_shared_out_of_order_tiles) { + // Find the first tiling with a tile. + while (tiling_index_ < tilings_->size()) { + if (!((*tilings_))[tiling_index_]->has_eventually_rect_tiles()) { + ++tiling_index_; + continue; + } + iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_eventually_rect(), + ((*tilings_))[tiling_index_]->current_skewport_rect(), + ((*tilings_))[tiling_index_]->current_soon_border_rect()); + if (!iterator_) { + ++tiling_index_; + continue; } break; } + if (tiling_index_ >= tilings_->size()) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} - TilePriority::PriorityBin max_tile_priority_bin = - current_tiling_->client_->GetMaxTilePriorityBin(); - while (visible_iterator_) { - std::pair<int, int> next_index = visible_iterator_.index(); - Tile* tile = current_tiling_->TileAt(next_index.first, next_index.second); - ++visible_iterator_; - if (!tile || !tile->HasResource()) +TilingSetEvictionQueue::EventuallyTilingIterator& + TilingSetEvictionQueue::EventuallyTilingIterator:: + operator++() { + bool found_tile = AdvanceToNextTile(&iterator_); + while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { + ++tiling_index_; + if (!((*tilings_))[tiling_index_]->has_eventually_rect_tiles()) continue; - // If the max tile priority is not NOW, updated priorities for tiles - // returned by the visible iterator will not have NOW (but EVENTUALLY) - // priority bin and cannot therefore be required for activation tiles nor - // occluded NOW tiles in the current tiling. - if (max_tile_priority_bin <= TilePriority::NOW) { - // If the current tiling is a pending tree tiling, required for - // activation tiles can be detected without updating tile priorities. - if (tree_ == PENDING_TREE && - current_tiling_->IsTileRequiredForActivationIfVisible(tile) != - required_for_activation) { - continue; - } - // Unoccluded NOW tiles should be evicted (and thus returned) only after - // all occluded NOW tiles. - if (!current_tiling_->IsTileOccluded(tile)) { - unoccluded_now_tiles_.push_back(tile); - continue; - } + iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_eventually_rect(), + ((*tilings_))[tiling_index_]->current_skewport_rect(), + ((*tilings_))[tiling_index_]->current_soon_border_rect()); + if (!iterator_) + continue; + found_tile = GetFirstTileAndCheckIfValid(&iterator_); + if (!found_tile) + found_tile = AdvanceToNextTile(&iterator_); + } + return *this; +} + +// SoonBorderTilingIterator +TilingSetEvictionQueue::SoonBorderTilingIterator::SoonBorderTilingIterator( + std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles) + : EvictionRectIterator(tilings, tree, skip_shared_out_of_order_tiles) { + // Find the first tiling with a tile. + while (tiling_index_ < tilings_->size()) { + if (!((*tilings_))[tiling_index_]->has_soon_border_rect_tiles()) { + ++tiling_index_; + continue; } - current_tiling_->UpdateTileAndTwinPriority(tile); - if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tree_, tile)) + iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_soon_border_rect(), + ((*tilings_))[tiling_index_]->current_skewport_rect(), + ((*tilings_))[tiling_index_]->current_visible_rect()); + if (!iterator_) { + ++tiling_index_; continue; - if (tile->required_for_activation() != required_for_activation) - continue; - current_eviction_tile_ = tile; - return true; - } - - while (!unoccluded_now_tiles_.empty()) { - // All (unoccluded) NOW tiles have the same priority bin (NOW) and the same - // distance to visible (0.0), so it does not matter that tiles are popped - // in reversed (FILO) order. - Tile* tile = unoccluded_now_tiles_.back(); - unoccluded_now_tiles_.pop_back(); - DCHECK(tile); - if (!tile->HasResource()) - continue; - current_tiling_->UpdateTileAndTwinPriority(tile); - if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tree_, tile)) - continue; - if (tile->required_for_activation() != required_for_activation) - continue; - current_eviction_tile_ = tile; - return true; - } - - current_eviction_tile_ = nullptr; - return false; -} - -bool TilingSetEvictionQueue::AdvanceToNextPriorityBin() { - // Advance to the next priority bin. This is done only after all tiling range - // types (including the required for activation tiling) within the previous - // priority bin have been gone through. - DCHECK_EQ(current_tiling_range_type_, PictureLayerTilingSet::HIGH_RES); - - switch (current_priority_bin_) { - case TilePriority::EVENTUALLY: - current_priority_bin_ = TilePriority::SOON; - return true; - case TilePriority::SOON: - current_priority_bin_ = TilePriority::NOW; - return true; - case TilePriority::NOW: - return false; - } - NOTREACHED(); - return false; -} - -bool TilingSetEvictionQueue::AdvanceToNextTilingRangeType() { - // Advance to the next tiling range type within the current priority bin, to - // the required for activation tiling range type within the current priority - // bin or to the first tiling range type within the next priority bin. This - // is done only after all tilings within the previous tiling range type have - // been gone through. - DCHECK_EQ(current_tiling_index_, CurrentTilingRange().end); - - switch (current_tiling_range_type_) { - case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES: - current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES; - return true; - case PictureLayerTilingSet::LOWER_THAN_LOW_RES: - current_tiling_range_type_ = - PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES; - return true; - case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES: - current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES; - return true; - case PictureLayerTilingSet::LOW_RES: - current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES; - return true; - case PictureLayerTilingSet::HIGH_RES: - // Process required for activation tiles (unless that has already been - // done). Only pending tree NOW tiles may be required for activation. - if (!processing_required_for_activation_tiles_ && - current_priority_bin_ == TilePriority::NOW && tree_ == PENDING_TREE) { - processing_required_for_activation_tiles_ = true; - return true; - } - processing_required_for_activation_tiles_ = false; - - if (!AdvanceToNextPriorityBin()) - return false; - - current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES; - return true; - } - NOTREACHED(); - return false; -} - -bool TilingSetEvictionQueue::AdvanceToNextValidTiling() { - // Advance to the next tiling within current tiling range type or to - // the first tiling within the next tiling range type or priority bin until - // the next eviction tile is found. This is done only after all eviction - // tiles within the previous tiling within the current priority bin and - // tiling range type have been gone through. - DCHECK(!current_eviction_tile_); - DCHECK_NE(current_tiling_index_, CurrentTilingRange().end); - - for (;;) { - ++current_tiling_index_; - while (current_tiling_index_ == CurrentTilingRange().end) { - if (!AdvanceToNextTilingRangeType()) - return false; - current_tiling_index_ = CurrentTilingRange().start; } - current_tiling_ = tiling_set_->tiling_at(CurrentTilingIndex()); + break; + } + if (tiling_index_ >= tilings_->size()) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} - switch (current_priority_bin_) { - case TilePriority::EVENTUALLY: - if (current_tiling_->has_eventually_rect_tiles_) { - spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( - ¤t_tiling_->tiling_data_, - current_tiling_->current_eventually_rect_, - current_tiling_->current_skewport_rect_, - current_tiling_->current_soon_border_rect_); - if (AdvanceToNextEvictionTile()) - return true; - } - break; - case TilePriority::SOON: - if (current_tiling_->has_skewport_rect_tiles_ || - current_tiling_->has_soon_border_rect_tiles_) { - processing_soon_border_rect_ = true; - if (current_tiling_->has_soon_border_rect_tiles_) - spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( - ¤t_tiling_->tiling_data_, - current_tiling_->current_soon_border_rect_, - current_tiling_->current_skewport_rect_, - current_tiling_->current_visible_rect_); - if (AdvanceToNextEvictionTile()) - return true; - } - break; - case TilePriority::NOW: - if (current_tiling_->has_visible_rect_tiles_) { - visible_iterator_ = - TilingData::Iterator(¤t_tiling_->tiling_data_, - current_tiling_->current_visible_rect_, - false /* include_borders */); - if (AdvanceToNextEvictionTile()) - return true; - } - break; +TilingSetEvictionQueue::SoonBorderTilingIterator& + TilingSetEvictionQueue::SoonBorderTilingIterator:: + operator++() { + bool found_tile = AdvanceToNextTile(&iterator_); + while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { + ++tiling_index_; + if (!((*tilings_))[tiling_index_]->has_soon_border_rect_tiles()) + continue; + iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_soon_border_rect(), + ((*tilings_))[tiling_index_]->current_skewport_rect(), + ((*tilings_))[tiling_index_]->current_visible_rect()); + if (!iterator_) + continue; + found_tile = GetFirstTileAndCheckIfValid(&iterator_); + if (!found_tile) + found_tile = AdvanceToNextTile(&iterator_); + } + return *this; +} + +// SkewportTilingIterator +TilingSetEvictionQueue::SkewportTilingIterator::SkewportTilingIterator( + std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles) + : EvictionRectIterator(tilings, tree, skip_shared_out_of_order_tiles) { + // Find the first tiling with a tile. + while (tiling_index_ < tilings_->size()) { + if (!((*tilings_))[tiling_index_]->has_skewport_rect_tiles()) { + ++tiling_index_; + continue; } + iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_skewport_rect(), + ((*tilings_))[tiling_index_]->current_visible_rect(), + ((*tilings_))[tiling_index_]->current_visible_rect()); + if (!iterator_) { + ++tiling_index_; + continue; + } + break; + } + if (tiling_index_ >= tilings_->size()) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} + +TilingSetEvictionQueue::SkewportTilingIterator& + TilingSetEvictionQueue::SkewportTilingIterator:: + operator++() { + bool found_tile = AdvanceToNextTile(&iterator_); + while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { + ++tiling_index_; + if (!((*tilings_))[tiling_index_]->has_skewport_rect_tiles()) + continue; + iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_skewport_rect(), + ((*tilings_))[tiling_index_]->current_visible_rect(), + ((*tilings_))[tiling_index_]->current_visible_rect()); + if (!iterator_) + continue; + found_tile = GetFirstTileAndCheckIfValid(&iterator_); + if (!found_tile) + found_tile = AdvanceToNextTile(&iterator_); + } + return *this; +} + +// VisibleTilingIterator +TilingSetEvictionQueue::VisibleTilingIterator::VisibleTilingIterator( + std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles, + bool return_occluded_tiles, + bool return_required_for_activation_tiles) + : EvictionRectIterator(tilings, tree, skip_shared_out_of_order_tiles), + return_occluded_tiles_(return_occluded_tiles), + return_required_for_activation_tiles_( + return_required_for_activation_tiles) { + // Find the first tiling with a tile. + while (tiling_index_ < tilings_->size()) { + if (!((*tilings_))[tiling_index_]->has_visible_rect_tiles()) { + ++tiling_index_; + continue; + } + iterator_ = TilingData::Iterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_visible_rect(), false); + if (!iterator_) { + ++tiling_index_; + continue; + } + break; + } + if (tiling_index_ >= tilings_->size()) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) { + ++(*this); + return; + } + if (!TileMatchesRequiredFlags(tile_)) { + ++(*this); + return; } } -PictureLayerTilingSet::TilingRange -TilingSetEvictionQueue::CurrentTilingRange() const { - return tiling_set_->GetTilingRange(current_tiling_range_type_); +TilingSetEvictionQueue::VisibleTilingIterator& + TilingSetEvictionQueue::VisibleTilingIterator:: + operator++() { + bool found_tile = AdvanceToNextTile(&iterator_); + while (found_tile && !TileMatchesRequiredFlags(tile_)) + found_tile = AdvanceToNextTile(&iterator_); + + while (!found_tile && (tiling_index_ + 1) < tilings_->size()) { + ++tiling_index_; + if (!((*tilings_))[tiling_index_]->has_visible_rect_tiles()) + continue; + iterator_ = TilingData::Iterator( + ((*tilings_))[tiling_index_]->tiling_data(), + ((*tilings_))[tiling_index_]->current_visible_rect(), false); + if (!iterator_) + continue; + found_tile = GetFirstTileAndCheckIfValid(&iterator_); + if (!found_tile) + found_tile = AdvanceToNextTile(&iterator_); + while (found_tile && !TileMatchesRequiredFlags(tile_)) + found_tile = AdvanceToNextTile(&iterator_); + } + return *this; } -size_t TilingSetEvictionQueue::CurrentTilingIndex() const { - DCHECK_NE(current_tiling_index_, CurrentTilingRange().end); - switch (current_tiling_range_type_) { - case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES: - case PictureLayerTilingSet::LOW_RES: - case PictureLayerTilingSet::HIGH_RES: - return current_tiling_index_; - // Tilings in the following ranges are accessed in reverse order. - case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES: - case PictureLayerTilingSet::LOWER_THAN_LOW_RES: { - PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange(); - size_t current_tiling_range_offset = - current_tiling_index_ - tiling_range.start; - return tiling_range.end - 1 - current_tiling_range_offset; - } - } - NOTREACHED(); - return 0; +bool TilingSetEvictionQueue::VisibleTilingIterator::TileMatchesRequiredFlags( + const Tile* tile) const { + bool activation_flag_matches = + tile->required_for_activation() == return_required_for_activation_tiles_; + bool occluded_flag_matches = + tile->is_occluded(tree_) == return_occluded_tiles_; + return activation_flag_matches && occluded_flag_matches; } } // namespace cc
diff --git a/cc/resources/tiling_set_eviction_queue.h b/cc/resources/tiling_set_eviction_queue.h index 6662a75..439bdbb 100644 --- a/cc/resources/tiling_set_eviction_queue.h +++ b/cc/resources/tiling_set_eviction_queue.h
@@ -13,58 +13,51 @@ namespace cc { // This eviction queue returned tiles from all tilings in a tiling set in -// the following order: -// 1) Eventually rect tiles (EVENTUALLY tiles). -// 1) Eventually rect tiles not required for activation from each tiling in -// the tiling set, in turn, in the following order: -// 1) the first higher than high res tiling, the second one and so on -// 2) the first lower than low res tiling, the second one and so on -// 3) the first between high and low res tiling, the second one and so on -// 4) low res tiling -// 5) high res tiling -// 2) Eventually rect tiles required for activation from the tiling with -// required for activation tiles. In the case of a pending tree tiling -// set that is the high res tiling. In the case of an active tree tiling -// set that is a tiling whose twin tiling is a pending tree high res -// tiling. -// 2) Soon border rect and skewport rect tiles (whose priority bin is SOON -// unless the max tile priority bin is lowered by PictureLayerTilingClient). -// 1) Soon border rect and skewport rect tiles not required for activation -// from each tiling in the tiling set. -// * Tilings are iterated in the same order as in the case of eventually -// rect tiles not required for activation. -// * For each tiling, first soon border rect tiles and then skewport -// rect tiles are returned. -// 2) Soon border rect and skewport rect tiles required for activation from -// the tiling with required for activation tiles. -// * First soon border rect tiles and then skewport rect tiles are -// returned. -// 3) Visible rect tiles (whose priority bin is NOW unless the max tile -// priority bin is lowered by PictureLayerTilingClient). -// 1) Visible rect tiles not required for activation from each tiling in -// the tiling set. -// * Tilings are iterated in the same order as in the case of eventually -// rect tiles not required for activation. -// * For each tiling, first occluded tiles and then unoccluded tiles -// are returned. -// 2) Visible rect tiles required for activation from the tiling with -// required for activation tiles. -// * First occluded tiles and then unoccluded tiles are returned. -// If the max tile priority bin is lowered by PictureLayerTilingClient, -// occlusion is not taken into account as occlusion is meaningful only for -// NOW tiles. +// the order in which the tiles should be evicted. It can be thought of as the +// following: +// for all phases: +// for all ordered tilings: +// yield the next tile for the given phase from the given tiling // -// Within each tiling and tile priority rect, tiles are returned in reverse -// spiral order i.e. in (mostly) decreasing distance-to-visible order. +// Phases are the following (in order in which they are processed): +// EVENTUALLY_RECT - Tiles in the eventually region of the tiling. +// SOON_BORDER_RECT - Tiles in the prepainting skirt of the tiling. +// SKEWPORT_RECT - Tiles in the skewport of the tiling. +// VISIBLE_RECT_OCCLUDED - Occluded, not required for activation, visible tiles. +// VISIBLE_RECT_UNOCCLUDED - Unoccluded, not required for activation, visible +// tiles. +// VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED - Occluded, but required for +// activation, visible tiles. This can happen when an active tree tile is +// occluded, but is not occluded on the pending tree (and is required for +// activation). +// VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED - Unoccluded, required for +// activation, tiles. // -// If the skip_shared_out_of_order_tiles value passed to the constructor is -// true (like it should be when there is a twin layer with a twin tiling set), -// eviction queue does not return shared which are out of order because their -// priority for tree priority is lowered or raised by a twin layer. -// This happens for a tile specific lower priority tree eviction queue -// (because eviction priority the combined priority). -// Those skipped shared out of order tiles are when returned only by the twin -// eviction queue. +// The tilings are ordered as follows. Suppose we have tilings with the scales +// below: +// 2.0 1.5 1.0(HR) 0.8 0.5 0.25(LR) 0.2 0.1 +// With HR referring to high res tiling and LR referring to low res tiling, +// then tilings are processed in this order: +// 2.0 1.5 0.1 0.2 0.5 0.8 0.25(LR) 1.0(HR). +// +// To put it differently: +// 1. Process the highest scale tiling down to, but not including, high res +// tiling. +// 2. Process the lowest scale tiling up to, but not including, the low res +// tiling. In cases without a low res tiling, this is an empty set. +// 3. Process low res tiling up to high res tiling, including neither high +// nor low res tilings. In cases without a low res tiling, this set +// includes all tilings with a lower scale than the high res tiling. +// 4. Process the low res tiling. +// 5. Process the high res tiling. +// +// Additional notes: +// Since eventually the tiles are considered to have the priority which is the +// higher of the two trees, we might visit a tile that should actually be +// returned by its twin. In those situations, the tiles are not returned. That +// is, since the twin has higher priority, it should return it when it gets to +// it. This ensures that we don't block raster because we've returned a tile +// with low priority on one tree, but high combined priority. class CC_EXPORT TilingSetEvictionQueue { public: TilingSetEvictionQueue(PictureLayerTilingSet* tiling_set, @@ -77,29 +70,114 @@ bool IsEmpty() const; private: - bool AdvanceToNextEvictionTile(); - bool AdvanceToNextPriorityBin(); - bool AdvanceToNextTilingRangeType(); - bool AdvanceToNextValidTiling(); + enum Phase { + EVENTUALLY_RECT, + SOON_BORDER_RECT, + SKEWPORT_RECT, + VISIBLE_RECT_OCCLUDED, + VISIBLE_RECT_UNOCCLUDED, + VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_OCCLUDED, + VISIBLE_RECT_REQUIRED_FOR_ACTIVATION_UNOCCLUDED + }; - PictureLayerTilingSet::TilingRange CurrentTilingRange() const; - size_t CurrentTilingIndex() const; + void GenerateTilingOrder(PictureLayerTilingSet* tiling_set); - PictureLayerTilingSet* tiling_set_; + // Helper base class for individual region iterators. + class EvictionRectIterator { + public: + EvictionRectIterator(); + EvictionRectIterator(std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles); + + bool done() const { return !tile_; } + Tile* operator*() const { return tile_; } + + protected: + ~EvictionRectIterator() = default; + + template <typename TilingIteratorType> + bool AdvanceToNextTile(TilingIteratorType* iterator); + template <typename TilingIteratorType> + bool GetFirstTileAndCheckIfValid(TilingIteratorType* iterator); + + Tile* tile_; + std::vector<PictureLayerTiling*>* tilings_; + WhichTree tree_; + bool skip_shared_out_of_order_tiles_; + size_t tiling_index_; + }; + + class VisibleTilingIterator : public EvictionRectIterator { + public: + VisibleTilingIterator() = default; + VisibleTilingIterator(std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles, + bool return_occluded_tiles, + bool return_required_for_activation_tiles); + + VisibleTilingIterator& operator++(); + + private: + bool TileMatchesRequiredFlags(const Tile* tile) const; + + TilingData::Iterator iterator_; + bool return_occluded_tiles_; + bool return_required_for_activation_tiles_; + }; + + class SkewportTilingIterator : public EvictionRectIterator { + public: + SkewportTilingIterator() = default; + SkewportTilingIterator(std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles); + + SkewportTilingIterator& operator++(); + + private: + TilingData::ReverseSpiralDifferenceIterator iterator_; + }; + + class SoonBorderTilingIterator : public EvictionRectIterator { + public: + SoonBorderTilingIterator() = default; + SoonBorderTilingIterator(std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles); + + SoonBorderTilingIterator& operator++(); + + private: + TilingData::ReverseSpiralDifferenceIterator iterator_; + }; + + class EventuallyTilingIterator : public EvictionRectIterator { + public: + EventuallyTilingIterator() = default; + EventuallyTilingIterator(std::vector<PictureLayerTiling*>* tilings, + WhichTree tree, + bool skip_shared_out_of_order_tiles); + + EventuallyTilingIterator& operator++(); + + private: + TilingData::ReverseSpiralDifferenceIterator iterator_; + }; + + void AdvancePhase(); + WhichTree tree_; bool skip_shared_out_of_order_tiles_; - bool processing_soon_border_rect_; - bool processing_required_for_activation_tiles_; + Phase phase_; + Tile* current_tile_; + std::vector<PictureLayerTiling*> tilings_; - TilePriority::PriorityBin current_priority_bin_; - PictureLayerTiling* current_tiling_; - size_t current_tiling_index_; - PictureLayerTilingSet::TilingRangeType current_tiling_range_type_; - Tile* current_eviction_tile_; - - TilingData::ReverseSpiralDifferenceIterator spiral_iterator_; - TilingData::Iterator visible_iterator_; - std::vector<Tile*> unoccluded_now_tiles_; + EventuallyTilingIterator eventually_iterator_; + SoonBorderTilingIterator soon_iterator_; + SkewportTilingIterator skewport_iterator_; + VisibleTilingIterator visible_iterator_; }; } // namespace cc
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index fc82b26..d52141f 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -49,21 +49,6 @@ } BeginFrameSource* -SchedulerFrameSourcesConstructor::ConstructBackgroundFrameSource( - Scheduler* scheduler) { - TRACE_EVENT1("cc", - "Scheduler::Scheduler()", - "BackgroundFrameSource", - "SyntheticBeginFrameSource"); - DCHECK(!(scheduler->background_frame_source_internal_)); - scheduler->background_frame_source_internal_ = - SyntheticBeginFrameSource::Create( - scheduler->task_runner_.get(), scheduler->Now(), - scheduler->settings_.background_frame_interval); - return scheduler->background_frame_source_internal_.get(); -} - -BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructUnthrottledFrameSource( Scheduler* scheduler) { TRACE_EVENT1("cc", "Scheduler::Scheduler()", "UnthrottledFrameSource", @@ -83,13 +68,11 @@ SchedulerFrameSourcesConstructor* frame_sources_constructor) : frame_source_(), primary_frame_source_(NULL), - background_frame_source_(NULL), primary_frame_source_internal_(external_begin_frame_source.Pass()), - background_frame_source_internal_(), vsync_observer_(NULL), authoritative_vsync_interval_(base::TimeDelta()), last_vsync_timebase_(base::TimeTicks()), - throttle_frame_production_(scheduler_settings.throttle_frame_production), + throttle_frame_production_(false), settings_(scheduler_settings), client_(client), layer_tree_host_id_(layer_tree_host_id), @@ -123,15 +106,12 @@ frame_source_->AddSource(primary_frame_source_); primary_frame_source_->SetClientReady(); - // Background ticking frame source - background_frame_source_ = - frame_sources_constructor->ConstructBackgroundFrameSource(this); - frame_source_->AddSource(background_frame_source_); - // Unthrottled frame source unthrottled_frame_source_ = frame_sources_constructor->ConstructUnthrottledFrameSource(this); frame_source_->AddSource(unthrottled_frame_source_); + + SetThrottleFrameProduction(scheduler_settings.throttle_frame_production); } Scheduler::~Scheduler() { @@ -173,22 +153,9 @@ ProcessScheduledActions(); } -void Scheduler::UpdateActiveFrameSource() { - if (state_machine_.visible()) { - if (throttle_frame_production_) { - frame_source_->SetActiveSource(primary_frame_source_); - } else { - frame_source_->SetActiveSource(unthrottled_frame_source_); - } - } else { - frame_source_->SetActiveSource(background_frame_source_); - } - ProcessScheduledActions(); -} - void Scheduler::SetVisible(bool visible) { state_machine_.SetVisible(visible); - UpdateActiveFrameSource(); + ProcessScheduledActions(); } void Scheduler::SetCanDraw(bool can_draw) { @@ -209,7 +176,12 @@ void Scheduler::SetThrottleFrameProduction(bool throttle) { throttle_frame_production_ = throttle; - UpdateActiveFrameSource(); + if (throttle) { + frame_source_->SetActiveSource(primary_frame_source_); + } else { + frame_source_->SetActiveSource(unthrottled_frame_source_); + } + ProcessScheduledActions(); } void Scheduler::SetNeedsCommit() {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 353fdcff..542438b 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h
@@ -64,8 +64,6 @@ public: virtual ~SchedulerFrameSourcesConstructor() {} virtual BeginFrameSource* ConstructPrimaryFrameSource(Scheduler* scheduler); - virtual BeginFrameSource* ConstructBackgroundFrameSource( - Scheduler* scheduler); virtual BeginFrameSource* ConstructUnthrottledFrameSource( Scheduler* scheduler); @@ -188,12 +186,10 @@ scoped_ptr<BeginFrameSourceMultiplexer> frame_source_; BeginFrameSource* primary_frame_source_; - BeginFrameSource* background_frame_source_; BeginFrameSource* unthrottled_frame_source_; // Storage when frame sources are internal scoped_ptr<BeginFrameSource> primary_frame_source_internal_; - scoped_ptr<SyntheticBeginFrameSource> background_frame_source_internal_; scoped_ptr<BeginFrameSource> unthrottled_frame_source_internal_; VSyncParameterObserver* vsync_observer_; @@ -243,7 +239,6 @@ void FinishImplFrame(); void OnBeginImplFrameDeadline(); void PollToAdvanceCommitState(); - void UpdateActiveFrameSource(); base::TimeDelta EstimatedParentDrawTime() { return estimated_parent_draw_time_;
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index 41de95dc..72e68ea 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc
@@ -720,7 +720,7 @@ skip_next_begin_main_frame_to_reduce_latency_ = true; } -bool SchedulerStateMachine::BeginFrameNeededForChildren() const { +bool SchedulerStateMachine::BeginFrameRequiredForChildren() const { return children_need_begin_frames_; } @@ -729,7 +729,12 @@ // TODO(brianderson): Support output surface creation inside a BeginFrame. if (!HasInitializedOutputSurface()) return false; - return (BeginFrameNeededToAnimateOrDraw() || BeginFrameNeededForChildren() || + + // If we are not visible, we don't need BeginFrame messages. + if (!visible_) + return false; + + return (BeginFrameRequiredForAction() || BeginFrameRequiredForChildren() || ProactiveBeginFrameWanted()); } @@ -742,29 +747,23 @@ defer_commits_ = defer_commits; } -// These are the cases where we definitely (or almost definitely) have a -// new frame to animate and/or draw and can draw. -bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const { +// These are the cases where we require a BeginFrame message to make progress +// on requested actions. +bool SchedulerStateMachine::BeginFrameRequiredForAction() const { // The forced draw respects our normal draw scheduling, so we need to // request a BeginImplFrame for it. if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) return true; - // TODO(mithro): Remove background animation ticking. crbug.com/371747 - if (needs_animate_) - return true; - - // Only background tick for animations - not draws, which will never happen. - if (!visible_) - return false; - - return needs_redraw_; + return needs_animate_ || needs_redraw_ || (needs_commit_ && !defer_commits_); } -// These are cases where we are very likely to draw soon, but might not -// actually have a new frame to draw when we receive the next BeginImplFrame. -// Proactively requesting the BeginImplFrame helps hide the round trip latency -// of the SetNeedsBeginFrame request that has to go to the Browser. +// These are cases where we are very likely want a BeginFrame message in the +// near future. Proactively requesting the BeginImplFrame helps hide the round +// trip latency of the SetNeedsBeginFrame request that has to go to the +// Browser. +// This includes things like drawing soon, but might not actually have a new +// frame to draw when we receive the next BeginImplFrame. bool SchedulerStateMachine::ProactiveBeginFrameWanted() const { // Do not be proactive when invisible. if (!visible_) @@ -775,7 +774,7 @@ // request frames when commits are disabled, because the frame requests will // not provide the needed commit (and will wake up the process when it could // stay idle). - if ((needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) && !defer_commits_) + if ((commit_state_ != COMMIT_STATE_IDLE) && !defer_commits_) return true; // If the pending tree activates quickly, we'll want a BeginImplFrame soon @@ -872,9 +871,9 @@ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) return false; - // If we've lost the output surface, end the current BeginImplFrame ASAP - // so we can start creating the next output surface. - if (output_surface_state_ == OUTPUT_SURFACE_LOST) + // If things are being aborted, end the current BeginImplFrame ASAP so we can + // unblock creating the next output surface. + if (PendingDrawsShouldBeAborted()) return true; // SwapAck throttle the deadline since we wont draw and swap anyway.
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h index 39f9faa..7d6810b 100644 --- a/cc/scheduler/scheduler_state_machine.h +++ b/cc/scheduler/scheduler_state_machine.h
@@ -255,8 +255,8 @@ } protected: - bool BeginFrameNeededToAnimateOrDraw() const; - bool BeginFrameNeededForChildren() const; + bool BeginFrameRequiredForAction() const; + bool BeginFrameRequiredForChildren() const; bool ProactiveBeginFrameWanted() const; bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index 0d94edb..7b332a3 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -171,12 +171,6 @@ state.SetNeedsAnimateForTest(false); EXPECT_FALSE(state.BeginFrameNeeded()); - // Background tick for animations. - state.SetVisible(false); - state.SetNeedsRedraw(false); - state.SetNeedsAnimateForTest(true); - EXPECT_TRUE(state.BeginFrameNeeded()); - // Proactively request BeginFrames when commit is pending. state.SetVisible(true); state.SetNeedsRedraw(false); @@ -248,6 +242,35 @@ EXPECT_TRUE(state.BeginFrameNeeded()); + // Expect nothing to happen until after OnBeginImplFrame. + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); + + state.OnBeginImplFrame(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + } + + // If commit requested and can't draw, still begin a main frame. + { + StateMachine state(default_scheduler_settings); + state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE); + state.SetCanStart(); + state.UpdateState(state.NextAction()); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + state.SetNeedsRedraw(false); + state.SetVisible(true); + state.SetNeedsCommit(); + state.SetCanDraw(false); + + EXPECT_TRUE(state.BeginFrameNeeded()); + + // Expect nothing to happen until after OnBeginImplFrame. + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); + state.OnBeginImplFrame(); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); @@ -1556,6 +1579,25 @@ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); } +TEST(SchedulerStateMachineTest, TestNoBeginFrameNeededWhenInvisible) { + SchedulerSettings default_scheduler_settings; + StateMachine state(default_scheduler_settings); + state.SetCanStart(); + state.UpdateState(state.NextAction()); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + state.SetVisible(true); + + EXPECT_FALSE(state.BeginFrameNeeded()); + state.SetNeedsRedraw(true); + EXPECT_TRUE(state.BeginFrameNeeded()); + + state.SetVisible(false); + EXPECT_FALSE(state.BeginFrameNeeded()); + + state.SetVisible(true); + EXPECT_TRUE(state.BeginFrameNeeded()); +} + TEST(SchedulerStateMachineTest, TestNoBeginMainFrameWhenInvisible) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); @@ -1565,6 +1607,14 @@ state.SetVisible(false); state.SetNeedsCommit(); EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); + EXPECT_FALSE(state.BeginFrameNeeded()); + + // When become visible again, the needs commit should still be pending. + state.SetVisible(true); + EXPECT_TRUE(state.BeginFrameNeeded()); + state.OnBeginImplFrame(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); } TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) { @@ -1762,6 +1812,25 @@ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); } +TEST(SchedulerStateMachineTest, TestTriggerDeadlineImmediatelyWhenInvisible) { + SchedulerSettings settings; + settings.impl_side_painting = true; + StateMachine state(settings); + SET_UP_STATE(state) + + state.SetNeedsCommit(); + + state.OnBeginImplFrame(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); + + state.SetVisible(false); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately()); +} + TEST(SchedulerStateMachineTest, TestSetNeedsAnimate) { SchedulerSettings settings; settings.impl_side_painting = true;
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 52f7c46..4ba6f4c 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -360,6 +360,7 @@ // it will be already in the task queue. if (scheduler_->settings().use_external_begin_frame_source && scheduler_->FrameProductionThrottled()) { + EXPECT_TRUE(client_->needs_begin_frames()); SendNextBeginFrame(); } @@ -2209,12 +2210,16 @@ scheduler_->NotifyBeginMainFrameStarted(); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); scheduler_->SetVisible(false); + task_runner().RunPendingTasks(); // Run posted deadline. + // Sync tree should be forced to activate. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); - EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); + EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3); + EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } // Tests to ensure frame sources can be successfully changed while drawing.
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc index 09dd77b..296c891 100644 --- a/cc/test/fake_content_layer_client.cc +++ b/cc/test/fake_content_layer_client.cc
@@ -89,7 +89,7 @@ skia::SharePtr(recorder.beginRecording(gfx::RectFToSkRect(draw_rect))); canvas->drawRectCoords(draw_rect.x(), draw_rect.y(), draw_rect.width(), draw_rect.height(), paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); } @@ -101,7 +101,7 @@ canvas = skia::SharePtr( recorder.beginRecording(it->bitmap.width(), it->bitmap.height())); canvas->drawBitmap(it->bitmap, it->point.x(), it->point.y(), &it->paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); if (!it->transform.IsIdentity()) { list->AppendItem(EndTransformDisplayItem::Create()); @@ -117,7 +117,7 @@ canvas = skia::SharePtr( recorder.beginRecording(gfx::RectFToSkRect(draw_rect))); canvas->drawRect(gfx::RectFToSkRect(draw_rect), paint); - picture = skia::AdoptRef(recorder.endRecording()); + picture = skia::AdoptRef(recorder.endRecordingAsPicture()); list->AppendItem(DrawingDisplayItem::Create(picture)); draw_rect.Inset(1, 1); }
diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc index f25d6eb..7f730de 100644 --- a/cc/test/scheduler_test_common.cc +++ b/cc/test/scheduler_test_common.cc
@@ -98,21 +98,6 @@ } BeginFrameSource* -TestSchedulerFrameSourcesConstructor::ConstructBackgroundFrameSource( - Scheduler* scheduler) { - TRACE_EVENT1( - "cc", - "TestSchedulerFrameSourcesConstructor::ConstructBackgroundFrameSource", - "source", - "TestSyntheticBeginFrameSource"); - DCHECK(!(scheduler->background_frame_source_internal_)); - scheduler->background_frame_source_internal_ = - TestSyntheticBeginFrameSource::Create( - now_src_, test_task_runner_, base::TimeDelta::FromSeconds(1)); - return scheduler->background_frame_source_internal_.get(); -} - -BeginFrameSource* TestSchedulerFrameSourcesConstructor::ConstructUnthrottledFrameSource( Scheduler* scheduler) { TRACE_EVENT1(
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h index 825c9a3d..633289ba 100644 --- a/cc/test/scheduler_test_common.h +++ b/cc/test/scheduler_test_common.h
@@ -141,8 +141,6 @@ protected: BeginFrameSource* ConstructPrimaryFrameSource(Scheduler* scheduler) override; - BeginFrameSource* ConstructBackgroundFrameSource( - Scheduler* scheduler) override; BeginFrameSource* ConstructUnthrottledFrameSource( Scheduler* scheduler) override;
diff --git a/cc/test/test_gpu_memory_buffer_manager.cc b/cc/test/test_gpu_memory_buffer_manager.cc index 8887feb..a3cd357 100644 --- a/cc/test/test_gpu_memory_buffer_manager.cc +++ b/cc/test/test_gpu_memory_buffer_manager.cc
@@ -18,6 +18,7 @@ case gfx::GpuMemoryBuffer::Format::DXT1: case gfx::GpuMemoryBuffer::Format::DXT5: case gfx::GpuMemoryBuffer::Format::ETC1: + case gfx::GpuMemoryBuffer::Format::R_8: case gfx::GpuMemoryBuffer::Format::RGBA_8888: case gfx::GpuMemoryBuffer::Format::RGBX_8888: case gfx::GpuMemoryBuffer::Format::BGRA_8888: @@ -36,6 +37,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::BGRA_8888: @@ -64,6 +66,8 @@ DCHECK_EQ(plane, 0); DCHECK_EQ(width % 2, 0U); return width / 2; + case gfx::GpuMemoryBuffer::R_8: + return (width + 3) & ~0x3; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::BGRA_8888:
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index df4c39ad..322d57e 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -45,7 +45,12 @@ target_is_root_surface ? 0 : transform_node->data.content_target_id; const TransformNode* target_node = transform_tree.Node(target_id); - gfx::Transform content_to_target = transform_node->data.to_target; + // TODO(ajuma): Try to re-use transforms already stored in the transform + // tree instead of computing transforms below. + gfx::Transform content_to_target; + bool success = transform_tree.ComputeTransform( + transform_node->id, target_node->id, &content_to_target); + DCHECK(success); content_to_target.Translate(layer->offset_to_transform_parent().x(), layer->offset_to_transform_parent().y()); @@ -53,18 +58,8 @@ gfx::Rect clip_rect_in_target_space; gfx::Transform clip_to_target; - bool success = true; - if (clip_transform_node->data.target_id == target_node->id) { - clip_to_target = clip_transform_node->data.to_target; - } else { - success = transform_tree.ComputeTransform( - clip_transform_node->id, target_node->id, &clip_to_target); - if (target_node->data.needs_sublayer_scale) { - clip_to_target.Scale(target_node->data.sublayer_scale.x(), - target_node->data.sublayer_scale.y()); - } - } - + success = transform_tree.ComputeTransform( + clip_transform_node->id, target_node->id, &clip_to_target); if (target_node->id > clip_node->data.transform_id) { if (!success) { DCHECK(target_node->data.to_screen_is_animated); @@ -101,19 +96,8 @@ gfx::Transform target_to_content; gfx::Transform target_to_layer; - if (transform_node->data.ancestors_are_invertible) { - target_to_layer = transform_node->data.from_target; - success = true; - } else { - success = transform_tree.ComputeTransform( - target_node->id, transform_node->id, &target_to_layer); - if (target_node->data.needs_sublayer_scale) { - target_to_layer.matrix().postScale( - 1.f / target_node->data.sublayer_scale.x(), - 1.f / target_node->data.sublayer_scale.y(), 1.f); - } - } - + success = transform_tree.ComputeTransform( + target_node->id, transform_node->id, &target_to_layer); if (!success) { DCHECK(transform_node->data.to_screen_is_animated); @@ -322,21 +306,20 @@ float device_scale_factor, const gfx::Rect& viewport, const gfx::Transform& device_transform, - TransformTree* transform_tree, - ClipTree* clip_tree, - OpacityTree* opacity_tree) { + PropertyTrees* property_trees) { PropertyTreeBuilder::BuildPropertyTrees( root_layer, page_scale_layer, page_scale_factor, device_scale_factor, - viewport, device_transform, transform_tree, clip_tree, opacity_tree); - ComputeTransforms(transform_tree); - ComputeClips(clip_tree, *transform_tree); + viewport, device_transform, property_trees); + ComputeTransforms(&property_trees->transform_tree); + ComputeClips(&property_trees->clip_tree, property_trees->transform_tree); std::vector<Layer*> layers_to_update; const bool subtree_is_visible_from_ancestor = true; - FindLayersThatNeedVisibleRects(root_layer, *transform_tree, + FindLayersThatNeedVisibleRects(root_layer, property_trees->transform_tree, subtree_is_visible_from_ancestor, &layers_to_update); - CalculateVisibleRects(layers_to_update, *clip_tree, *transform_tree); + CalculateVisibleRects(layers_to_update, property_trees->clip_tree, + property_trees->transform_tree); } } // namespace cc
diff --git a/cc/trees/draw_property_utils.h b/cc/trees/draw_property_utils.h index 78c3c53f..cf1fde42 100644 --- a/cc/trees/draw_property_utils.h +++ b/cc/trees/draw_property_utils.h
@@ -18,6 +18,7 @@ class Layer; class OpacityTree; class TransformTree; +class PropertyTrees; // Computes combined clips for every node in |clip_tree|. This function requires // that |transform_tree| has been updated via |ComputeTransforms|. @@ -40,9 +41,7 @@ float device_scale_factor, const gfx::Rect& viewport, const gfx::Transform& device_transform, - TransformTree* transform_tree, - ClipTree* clip_tree, - OpacityTree* opacity_tree); + PropertyTrees* property_trees); } // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 890d3040..53bfcb8f 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -796,6 +796,7 @@ // that we won't be able to detect if a layer is part of |update_list|. // Change this if this information is required. int render_surface_layer_list_id = 0; + PropertyTrees property_trees; LayerTreeHostCommon::CalcDrawPropsMainInputs inputs( root_layer, device_viewport_size(), gfx::Transform(), device_scale_factor_, page_scale_factor_, page_scale_layer, @@ -805,7 +806,7 @@ can_render_to_separate_surface, settings_.layer_transforms_should_scale_layer_contents, settings_.verify_property_trees, &update_list, - render_surface_layer_list_id); + render_surface_layer_list_id, &property_trees); LayerTreeHostCommon::CalculateDrawProperties(&inputs); }
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 68bb22c..038c259 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -2504,9 +2504,6 @@ // The translation from layer to property trees is an intermediate state. We // will eventually get these data passed directly to the compositor. - TransformTree transform_tree; - ClipTree clip_tree; - OpacityTree opacity_tree; { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"), "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees"); @@ -2514,7 +2511,7 @@ inputs->root_layer, inputs->page_scale_application_layer, inputs->page_scale_factor, inputs->device_scale_factor, gfx::Rect(inputs->device_viewport_size), inputs->device_transform, - &transform_tree, &clip_tree, &opacity_tree); + inputs->property_trees); } LayerIterator<Layer> it, end; @@ -2533,14 +2530,16 @@ << " actual: " << current_layer->visible_rect_from_property_trees().ToString(); - const bool draw_transforms_match = ApproximatelyEqual( - current_layer->draw_transform(), - current_layer->draw_transform_from_property_trees(transform_tree)); + const bool draw_transforms_match = + ApproximatelyEqual(current_layer->draw_transform(), + current_layer->draw_transform_from_property_trees( + inputs->property_trees->transform_tree)); CHECK(draw_transforms_match); const bool draw_opacities_match = current_layer->draw_opacity() == - current_layer->DrawOpacityFromPropertyTrees(opacity_tree); + current_layer->DrawOpacityFromPropertyTrees( + inputs->property_trees->opacity_tree); CHECK(draw_opacities_match); } }
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h index 404f407..030d07a8 100644 --- a/cc/trees/layer_tree_host_common.h +++ b/cc/trees/layer_tree_host_common.h
@@ -13,6 +13,7 @@ #include "cc/base/cc_export.h" #include "cc/base/scoped_ptr_vector.h" #include "cc/layers/layer_lists.h" +#include "cc/trees/property_tree.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/transform.h" @@ -22,6 +23,7 @@ class LayerImpl; class Layer; class SwapPromise; +class PropertyTrees; class CC_EXPORT LayerTreeHostCommon { public: @@ -47,7 +49,8 @@ bool can_adjust_raster_scales, bool verify_property_trees, RenderSurfaceLayerListType* render_surface_layer_list, - int current_render_surface_layer_list_id) + int current_render_surface_layer_list_id, + PropertyTrees* property_trees) : root_layer(root_layer), device_viewport_size(device_viewport_size), device_transform(device_transform), @@ -65,7 +68,8 @@ verify_property_trees(verify_property_trees), render_surface_layer_list(render_surface_layer_list), current_render_surface_layer_list_id( - current_render_surface_layer_list_id) {} + current_render_surface_layer_list_id), + property_trees(property_trees) {} LayerType* root_layer; gfx::Size device_viewport_size; @@ -83,6 +87,7 @@ bool verify_property_trees; RenderSurfaceLayerListType* render_surface_layer_list; int current_render_surface_layer_list_id; + PropertyTrees* property_trees; }; template <typename LayerType, typename RenderSurfaceLayerListType> @@ -100,6 +105,7 @@ private: const gfx::Transform identity_transform_; + PropertyTrees property_trees; }; typedef CalcDrawPropsInputs<Layer, RenderSurfaceLayerList> @@ -251,7 +257,8 @@ false, true, render_surface_layer_list, - 0) { + 0, + &property_trees) { DCHECK(root_layer); DCHECK(render_surface_layer_list); } @@ -279,7 +286,8 @@ false, true, render_surface_layer_list, - 0) { + 0, + &property_trees) { DCHECK(root_layer); DCHECK(render_surface_layer_list); }
diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc index be15bdee..9a5de06 100644 --- a/cc/trees/layer_tree_host_common_perftest.cc +++ b/cc/trees/layer_tree_host_common_perftest.cc
@@ -89,6 +89,7 @@ bool verify_property_trees = false; int max_texture_size = 8096; RenderSurfaceLayerList update_list; + PropertyTrees property_trees; LayerTreeHostCommon::CalcDrawPropsMainInputs inputs( layer_tree_host()->root_layer(), layer_tree_host()->device_viewport_size(), gfx::Transform(), @@ -103,7 +104,7 @@ layer_tree_host() ->settings() .layer_transforms_should_scale_layer_contents, - verify_property_trees, &update_list, 0); + verify_property_trees, &update_list, 0, &property_trees); LayerTreeHostCommon::CalculateDrawProperties(&inputs); timer_.NextLap(); @@ -144,6 +145,7 @@ LayerTreeImpl* active_tree, LayerTreeHostImpl* host_impl) { LayerImplList update_list; + PropertyTrees property_trees; bool verify_property_trees = false; LayerTreeHostCommon::CalcDrawPropsImplInputs inputs( active_tree->root_layer(), active_tree->DrawViewportSize(), @@ -156,7 +158,7 @@ host_impl->settings().layers_always_allowed_lcd_text, can_render_to_separate_surface, host_impl->settings().layer_transforms_should_scale_layer_contents, - verify_property_trees, &update_list, 0); + verify_property_trees, &update_list, 0, &property_trees); LayerTreeHostCommon::CalculateDrawProperties(&inputs); } };
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index e9b877d..93202a0 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -223,235 +223,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted); -// Ensures that animations continue to be ticked when we are backgrounded. -class LayerTreeHostAnimationTestTickAnimationWhileBackgrounded - : public LayerTreeHostAnimationTest { - public: - LayerTreeHostAnimationTestTickAnimationWhileBackgrounded() - : num_begin_frames_(0) {} - - void BeginTest() override { - PostAddLongAnimationToMainThread(layer_tree_host()->root_layer()); - } - - // Use WillAnimateLayers to set visible false before the animation runs and - // causes a commit, so we block the second visible animate in single-thread - // mode. - void WillAnimateLayers(LayerTreeHostImpl* host_impl, - base::TimeTicks monotonic_time) override { - // Verify that the host can draw, it's just not visible. - EXPECT_TRUE(host_impl->CanDraw()); - if (num_begin_frames_ < 2) { - if (!num_begin_frames_) { - // We have a long animation running. It should continue to tick even - // if we are not visible. - PostSetVisibleToMainThread(false); - } - num_begin_frames_++; - return; - } - EndTest(); - } - - void AfterTest() override {} - - private: - int num_begin_frames_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostAnimationTestTickAnimationWhileBackgrounded); - -// Ensures that animation time remains monotonic when we switch from foreground -// to background ticking and back, even if we're skipping draws due to -// checkerboarding when in the foreground. -class LayerTreeHostAnimationTestAnimationTickTimeIsMonotonic - : public LayerTreeHostAnimationTest { - public: - LayerTreeHostAnimationTestAnimationTickTimeIsMonotonic() - : has_background_ticked_(false), num_foreground_animates_(0) {} - - void InitializeSettings(LayerTreeSettings* settings) override { - // Make sure that drawing many times doesn't cause a checkerboarded - // animation to start so we avoid flake in this test. - settings->timeout_and_draw_when_animation_checkerboards = false; - } - - void BeginTest() override { - PostAddLongAnimationToMainThread(layer_tree_host()->root_layer()); - } - - void AnimateLayers(LayerTreeHostImpl* host_impl, - base::TimeTicks monotonic_time) override { - EXPECT_GE(monotonic_time, last_tick_time_); - last_tick_time_ = monotonic_time; - if (host_impl->visible()) { - num_foreground_animates_++; - if (num_foreground_animates_ > 1 && !has_background_ticked_) - PostSetVisibleToMainThread(false); - else if (has_background_ticked_) - EndTest(); - } else { - has_background_ticked_ = true; - PostSetVisibleToMainThread(true); - } - } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame, - DrawResult draw_result) override { - if (TestEnded()) - return draw_result; - return DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; - } - - void AfterTest() override {} - - private: - bool has_background_ticked_; - int num_foreground_animates_; - base::TimeTicks last_tick_time_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostAnimationTestAnimationTickTimeIsMonotonic); - -// Ensures that animations do not tick when we are backgrounded and -// and we have an empty active tree. -class LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree - : public LayerTreeHostAnimationTest { - protected: - LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree() - : active_tree_was_animated_(false) {} - - base::TimeDelta BackgroundAnimationInterval(LayerTreeHostImpl* host_impl) { - return base::TimeDelta::FromSecondsD( - 1.0 / host_impl->settings().background_animation_rate); - } - - void BeginTest() override { - PostAddAnimationToMainThread(layer_tree_host()->root_layer()); - } - - void NotifyAnimationFinished(base::TimeTicks monotonic_time, - Animation::TargetProperty target_property, - int group) override { - // Replace animated commits with an empty tree. - layer_tree_host()->SetRootLayer(make_scoped_refptr<Layer>(NULL)); - } - - void DidCommit() override { - // This alternates setting an empty tree and a non-empty tree with an - // animation. - switch (layer_tree_host()->source_frame_number()) { - case 1: - // Wait for NotifyAnimationFinished to commit an empty tree. - break; - case 2: - SetupTree(); - AddOpacityTransitionToLayer( - layer_tree_host()->root_layer(), 0.000001, 0, 0.5, true); - break; - case 3: - // Wait for NotifyAnimationFinished to commit an empty tree. - break; - case 4: - EndTest(); - break; - } - } - - void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override { - // At the start of every commit, block activations and make sure - // we are backgrounded. - if (host_impl->settings().impl_side_painting) - host_impl->BlockNotifyReadyToActivateForTesting(true); - PostSetVisibleToMainThread(false); - } - - void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { - if (!host_impl->settings().impl_side_painting) { - // There are no activations to block if we're not impl-side-painting, - // so just advance the test immediately. - if (host_impl->active_tree()->source_frame_number() < 3) - UnblockActivations(host_impl); - return; - } - - // We block activation for several ticks to make sure that, even though - // there is a pending tree with animations, we still do not background - // tick if the active tree is empty. - if (host_impl->pending_tree()->source_frame_number() < 3) { - base::MessageLoopProxy::current()->PostDelayedTask( - FROM_HERE, - base::Bind( - &LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree:: - UnblockActivations, - base::Unretained(this), host_impl), - 4 * BackgroundAnimationInterval(host_impl)); - } - } - - virtual void UnblockActivations(LayerTreeHostImpl* host_impl) { - if (host_impl->settings().impl_side_painting) - host_impl->BlockNotifyReadyToActivateForTesting(false); - } - - void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { - active_tree_was_animated_ = false; - - // Verify that commits are actually alternating with empty / non-empty - // trees. - int frame_number = host_impl->active_tree()->source_frame_number(); - switch (frame_number) { - case 0: - case 2: - EXPECT_TRUE(host_impl->active_tree()->root_layer()) - << "frame: " << frame_number; - break; - case 1: - case 3: - EXPECT_FALSE(host_impl->active_tree()->root_layer()) - << "frame: " << frame_number; - break; - } - - if (host_impl->active_tree()->source_frame_number() < 3) { - // Initiate the next commit after a delay to give us a chance to - // background tick if the active tree isn't empty. - base::MessageLoopProxy::current()->PostDelayedTask( - FROM_HERE, - base::Bind( - &LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree:: - InitiateNextCommit, - base::Unretained(this), host_impl), - 4 * BackgroundAnimationInterval(host_impl)); - } - } - - void WillAnimateLayers(LayerTreeHostImpl* host_impl, - base::TimeTicks monotonic_time) override { - EXPECT_TRUE(host_impl->active_tree()->root_layer()); - active_tree_was_animated_ = true; - } - - void InitiateNextCommit(LayerTreeHostImpl* host_impl) { - // Verify that we actually animated when we should have. - bool has_active_tree = host_impl->active_tree()->root_layer(); - EXPECT_EQ(has_active_tree, active_tree_was_animated_); - - // The next commit is blocked until we become visible again. - PostSetVisibleToMainThread(true); - } - - void AfterTest() override {} - - bool active_tree_was_animated_; -}; - -SINGLE_AND_MULTI_THREAD_BLOCKNOTIFY_TEST_F( - LayerTreeHostAnimationTestNoBackgroundTickingWithoutActiveTree); - // Ensure that an animation's timing function is respected. class LayerTreeHostAnimationTestAddAnimationWithTimingFunction : public LayerTreeHostAnimationTest { @@ -821,58 +592,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostAnimationTestRunAnimationWhenNotCanDraw); -// Make sure the main thread can still execute animations when the renderer is -// backgrounded. -class LayerTreeHostAnimationTestRunAnimationWhenNotVisible - : public LayerTreeHostAnimationTest { - public: - LayerTreeHostAnimationTestRunAnimationWhenNotVisible() : started_times_(0) {} - - void SetupTree() override { - LayerTreeHostAnimationTest::SetupTree(); - content_ = FakeContentLayer::Create(&client_); - content_->SetBounds(gfx::Size(4, 4)); - content_->set_layer_animation_delegate(this); - layer_tree_host()->root_layer()->AddChild(content_); - } - - void BeginTest() override { - visible_ = true; - PostAddAnimationToMainThread(content_.get()); - } - - void DidCommit() override { - visible_ = false; - layer_tree_host()->SetVisible(false); - } - - void NotifyAnimationStarted(base::TimeTicks monotonic_time, - Animation::TargetProperty target_property, - int group) override { - EXPECT_FALSE(visible_); - started_times_++; - } - - void NotifyAnimationFinished(base::TimeTicks monotonic_time, - Animation::TargetProperty target_property, - int group) override { - EXPECT_FALSE(visible_); - EXPECT_EQ(1, started_times_); - EndTest(); - } - - void AfterTest() override {} - - private: - bool visible_; - int started_times_; - FakeContentLayerClient client_; - scoped_refptr<FakeContentLayer> content_; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostAnimationTestRunAnimationWhenNotVisible); - // Animations should not be started when frames are being skipped due to // checkerboard. class LayerTreeHostAnimationTestCheckerboardDoesntStartAnimations
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index b831bb38..43c4bfb 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -8,7 +8,6 @@ #include <limits> #include <set> -#include "base/auto_reset.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/animation/keyframed_animation_curve.h" @@ -500,9 +499,6 @@ outer_viewport_scroll_layer_id == Layer::INVALID_ID); HideInnerViewportScrollbarsIfNearMinimumScale(); - - if (!root_layer_scroll_offset_delegate_) - return; } void LayerTreeImpl::ClearViewportLayers() { @@ -543,6 +539,10 @@ DRAW_MODE_RESOURCELESS_SOFTWARE); ++render_surface_layer_list_id_; + + // TODO(enne): Synchronize property trees to compositor thread and use + // them here. + PropertyTrees* property_trees = nullptr; LayerTreeHostCommon::CalcDrawPropsImplInputs inputs( root_layer(), DrawViewportSize(), layer_tree_host_impl_->DrawTransform(), device_scale_factor(), @@ -552,8 +552,8 @@ settings().can_use_lcd_text, settings().layers_always_allowed_lcd_text, can_render_to_separate_surface, settings().layer_transforms_should_scale_layer_contents, - settings().verify_property_trees, - &render_surface_layer_list_, render_surface_layer_list_id_); + settings().verify_property_trees, &render_surface_layer_list_, + render_surface_layer_list_id_, property_trees); LayerTreeHostCommon::CalculateDrawProperties(&inputs); }
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index ea0b2ed..b1fd5e4 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -312,7 +312,8 @@ gfx::Transform delta = node->data.from_target; delta *= rounded; - DCHECK(delta.IsIdentityOr2DTranslation()); + DCHECK(delta.IsApproximatelyIdentityOrTranslation(SkDoubleToMScalar(1e-4))) + << delta.ToString(); gfx::Vector2dF translation = delta.To2dTranslation();
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 00dc8d5..75c0079e 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -197,6 +197,13 @@ class CC_EXPORT OpacityTree final : public PropertyTree<OpacityNode> {}; +class CC_EXPORT PropertyTrees final { + public: + TransformTree transform_tree; + OpacityTree opacity_tree; + ClipTree clip_tree; +}; + } // namespace cc #endif // CC_TREES_PROPERTY_TREE_H_
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 9009bc9..67152d0e 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -318,13 +318,11 @@ float device_scale_factor, const gfx::Rect& viewport, const gfx::Transform& device_transform, - TransformTree* transform_tree, - ClipTree* clip_tree, - OpacityTree* opacity_tree) { + PropertyTrees* property_trees) { DataForRecursion data_for_recursion; - data_for_recursion.transform_tree = transform_tree; - data_for_recursion.clip_tree = clip_tree; - data_for_recursion.opacity_tree = opacity_tree; + data_for_recursion.transform_tree = &property_trees->transform_tree; + data_for_recursion.clip_tree = &property_trees->clip_tree; + data_for_recursion.opacity_tree = &property_trees->opacity_tree; data_for_recursion.transform_tree_parent = nullptr; data_for_recursion.transform_fixed_parent = nullptr; data_for_recursion.render_target = root_layer; @@ -340,7 +338,8 @@ ClipNode root_clip; root_clip.data.clip = viewport; root_clip.data.transform_id = 0; - data_for_recursion.clip_tree_parent = clip_tree->Insert(root_clip, 0); + data_for_recursion.clip_tree_parent = + data_for_recursion.clip_tree->Insert(root_clip, 0); BuildPropertyTreesInternal(root_layer, data_for_recursion); }
diff --git a/cc/trees/property_tree_builder.h b/cc/trees/property_tree_builder.h index 7f5f479e..0635e3b4 100644 --- a/cc/trees/property_tree_builder.h +++ b/cc/trees/property_tree_builder.h
@@ -24,9 +24,7 @@ float device_scale_factor, const gfx::Rect& viewport, const gfx::Transform& device_transform, - TransformTree* transform_tree, - ClipTree* clip_tree, - OpacityTree* opacity_tree); + PropertyTrees* property_trees); }; } // namespace cc
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 229863c..feb8ae5 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -22,6 +22,7 @@ sources = [ "app/chrome_exe_resource.h", ] + defines = [] deps = [] datadeps = [] @@ -51,6 +52,13 @@ "common/crash_keys.cc", "common/crash_keys.h'", ] + + if (is_component_build) { + # This is necessary to make content_switches compile without DLL + # linkage errors in a component build. + defines += [ "COMPILE_CONTENT_STATICALLY" ] + } + deps += [ ":chrome_version_resources", ":image_pre_reader", @@ -206,7 +214,7 @@ #TODO(GYP) add chrome_multiple_dll support if (false) { #chrome_multiple_dll) { - defines = [ "CHROME_MULTIPLE_DLL_BROWSER" ] + defines += [ "CHROME_MULTIPLE_DLL_BROWSER" ] deps += [ "//content/public/app:browser" ] } else { deps += [
diff --git a/chrome/VERSION b/chrome/VERSION index 7baa0bd..bb8720c 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=44 MINOR=0 -BUILD=2360 +BUILD=2363 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromiumApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromiumApplication.java index 053c041a..5c85ef3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromiumApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromiumApplication.java
@@ -37,6 +37,7 @@ import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferences; import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences; import org.chromium.chrome.browser.services.AndroidEduOwnerCheckCallback; +import org.chromium.chrome.browser.smartcard.PKCS11AuthenticationManager; import org.chromium.content.app.ContentApplication; import org.chromium.content.browser.BrowserStartupController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/PKCS11AuthenticationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/PKCS11AuthenticationManager.java index 43643e8f..1e4cb1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/PKCS11AuthenticationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/PKCS11AuthenticationManager.java
@@ -4,43 +4,12 @@ package org.chromium.chrome.browser; -import android.content.Context; - -import org.chromium.net.AndroidPrivateKey; - -import java.security.cert.X509Certificate; +import org.chromium.base.annotations.SuppressFBWarnings; /** * Defines API for managing interaction with SmartCard-based certificate storage using PKCS11. */ -public interface PKCS11AuthenticationManager { - - /** - * @return true iff SmartCard-based authentication is available. - */ - public boolean isPKCS11AuthEnabled(); - - /** - * Retrieves the preferred client certificate alias for the given host, port pair, or null if - * none can be retrieved. - * - * @param hostName The host for which to retrieve client certificate. - * @param port The port to use in conjunction with host to retrieve client certificate. - */ - public String getClientCertificateAlias(String hostName, int port); - - /** - * Returns the X509Certificate chain for the requested alias, or null if no there is no result. - */ - public X509Certificate[] getCertificateChain(String alias); - - /** - * Performs necessary initializing for using a PKCS11-based KeysStore. - */ - public void initialize(Context context); - - /** - * Returns the AndroidPrivateKey for the requested alias, or null if there is no result. - */ - public AndroidPrivateKey getPrivateKey(String alias); -} +// TODO(changwan): remove this after downstream change is merged. +@SuppressFBWarnings("NM_SAME_SIMPLE_NAME_AS_INTERFACE") +public interface PKCS11AuthenticationManager + extends org.chromium.chrome.browser.smartcard.PKCS11AuthenticationManager {} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SSLClientCertificateRequest.java b/chrome/android/java/src/org/chromium/chrome/browser/SSLClientCertificateRequest.java index 55b9c77..fd6eba9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SSLClientCertificateRequest.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SSLClientCertificateRequest.java
@@ -15,6 +15,7 @@ import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; import org.chromium.base.ThreadUtils; +import org.chromium.chrome.browser.smartcard.PKCS11AuthenticationManager; import org.chromium.net.AndroidPrivateKey; import org.chromium.net.DefaultAndroidKeyStore; import org.chromium.ui.base.WindowAndroid;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java index 0aca77e2..773632c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java
@@ -14,7 +14,6 @@ import org.chromium.ui.autofill.AutofillPopup; import org.chromium.ui.autofill.AutofillPopup.AutofillPopupDelegate; import org.chromium.ui.autofill.AutofillSuggestion; -import org.chromium.ui.base.ViewAndroid; import org.chromium.ui.base.ViewAndroidDelegate; import org.chromium.ui.base.WindowAndroid; @@ -47,9 +46,9 @@ @CalledByNative private static AutofillPopupBridge create(long nativeAutofillPopupViewAndroid, - WindowAndroid windowAndroid, ViewAndroid viewAndroid) { - return new AutofillPopupBridge(nativeAutofillPopupViewAndroid, windowAndroid, - viewAndroid.getViewAndroidDelegate()); + WindowAndroid windowAndroid, ViewAndroidDelegate viewAndroidDelegate) { + return new AutofillPopupBridge( + nativeAutofillPopupViewAndroid, windowAndroid, viewAndroidDelegate); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java index a19e12a..9703a00a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java
@@ -14,7 +14,6 @@ import org.chromium.base.JNINamespace; import org.chromium.ui.DropdownPopupWindow; import org.chromium.ui.R; -import org.chromium.ui.base.ViewAndroid; import org.chromium.ui.base.ViewAndroidDelegate; import org.chromium.ui.base.WindowAndroid; @@ -37,9 +36,8 @@ */ @CalledByNative private static PasswordGenerationPopupBridge create(long nativePopup, - WindowAndroid windowAndroid, ViewAndroid viewAndroid) { - return new PasswordGenerationPopupBridge(nativePopup, windowAndroid, - viewAndroid.getViewAndroidDelegate()); + WindowAndroid windowAndroid, ViewAndroidDelegate viewAndroidDelegate) { + return new PasswordGenerationPopupBridge(nativePopup, windowAndroid, viewAndroidDelegate); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/OverflowSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/OverflowSelector.java index b41d005..8eed872 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/OverflowSelector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/OverflowSelector.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.preferences.PreferencesLauncher; +import org.chromium.chrome.browser.preferences.password.ManageSavedPasswordsPreferences; import org.chromium.chrome.browser.widget.ButtonCompat; /** @@ -56,9 +57,8 @@ private static boolean processMenuItem(MenuItem item, Context context) { if (item.getItemId() == R.id.settings) { - // TODO(melandory) When Smart Lock setting will be implemented for Chrome on Android - // this code should open settings fragment with Smart Lock parameters. - PreferencesLauncher.launchSettingsPage(context, null); + PreferencesLauncher.launchSettingsPage( + context, ManageSavedPasswordsPreferences.class.getName()); return true; } // TODO(melandory): Learn more should open link to help center
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/smartcard/EmptyPKCS11AuthenticationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/smartcard/EmptyPKCS11AuthenticationManager.java new file mode 100644 index 0000000..d475f34 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/smartcard/EmptyPKCS11AuthenticationManager.java
@@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.smartcard; + +import android.content.Context; + +import org.chromium.base.ThreadUtils; +import org.chromium.net.AndroidPrivateKey; + +import java.security.cert.X509Certificate; + +/** + * Stub implementation of PKCS11AuthenticationManager. + */ +public class EmptyPKCS11AuthenticationManager implements PKCS11AuthenticationManager { + private static PKCS11AuthenticationManager sInstance; + + public static PKCS11AuthenticationManager getInstance() { + ThreadUtils.assertOnUiThread(); + if (sInstance == null) sInstance = new EmptyPKCS11AuthenticationManager(); + return sInstance; + } + + protected EmptyPKCS11AuthenticationManager() {} + + @Override + public boolean isPKCS11AuthEnabled() { + return false; + } + + @Override + public String getClientCertificateAlias(String hostName, int port) { + return null; + } + + @Override + public void initialize(Context context) {} + + @Override + public X509Certificate[] getCertificateChain(String alias) { + return null; + } + + @Override + public AndroidPrivateKey getPrivateKey(String alias) { + return null; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/smartcard/PKCS11AuthenticationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/smartcard/PKCS11AuthenticationManager.java new file mode 100644 index 0000000..5cc66e2 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/smartcard/PKCS11AuthenticationManager.java
@@ -0,0 +1,45 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.smartcard; + +import android.content.Context; + +import org.chromium.net.AndroidPrivateKey; + +import java.security.cert.X509Certificate; + +/** + * Defines API for managing interaction with SmartCard-based certificate storage using PKCS11. + */ +public interface PKCS11AuthenticationManager { + /** + * @return true iff SmartCard-based authentication is available. + */ + public boolean isPKCS11AuthEnabled(); + + /** + * Retrieves the preferred client certificate alias for the given host, port pair, or null if + * none can be retrieved. + * + * @param hostName The host for which to retrieve client certificate. + * @param port The port to use in conjunction with host to retrieve client certificate. + */ + public String getClientCertificateAlias(String hostName, int port); + + /** + * Returns the X509Certificate chain for the requested alias, or null if no there is no result. + */ + public X509Certificate[] getCertificateChain(String alias); + + /** + * Performs necessary initializing for using a PKCS11-based KeysStore. + */ + public void initialize(Context context); + + /** + * Returns the AndroidPrivateKey for the requested alias, or null if there is no result. + */ + public AndroidPrivateKey getPrivateKey(String alias); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java index 4f7c870..92bf19e0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java
@@ -53,7 +53,7 @@ @VisibleForTesting public static final String SESSION_TAG_PREFIX = "session_sync"; - private static ProfileSyncService sSyncSetupManager; + private static ProfileSyncService sProfileSyncService; @VisibleForTesting protected final Context mContext; @@ -76,16 +76,21 @@ @SuppressFBWarnings("LI_LAZY_INIT") public static ProfileSyncService get(Context context) { ThreadUtils.assertOnUiThread(); - if (sSyncSetupManager == null) { - sSyncSetupManager = new ProfileSyncService(context); + if (sProfileSyncService == null) { + sProfileSyncService = new ProfileSyncService(context); } - return sSyncSetupManager; + return sProfileSyncService; + } + + @VisibleForTesting + public static void overrideForTests(ProfileSyncService profileSyncService) { + sProfileSyncService = profileSyncService; } /** * This is called pretty early in our application. Avoid any blocking operations here. */ - private ProfileSyncService(Context context) { + protected ProfileSyncService(Context context) { ThreadUtils.assertOnUiThread(); // We should store the application context, as we outlive any activity which may create us. mContext = context.getApplicationContext();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java index 6a3eff4..70a7584 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java
@@ -33,7 +33,8 @@ public static final String FRAGMENT_PASSWORD = "password_fragment"; public static final String FRAGMENT_SPINNER = "spinner_fragment"; private static final String TAG = "PassphraseActivity"; - private static ProfileSyncService.SyncStateChangedListener sSyncStateChangedListener; + + private ProfileSyncService.SyncStateChangedListener mSyncStateChangedListener; @Override protected void onCreate(Bundle savedInstanceState) { @@ -71,11 +72,19 @@ } } + @Override + protected void onPause() { + super.onPause(); + // Make sure we don't receive callbacks while in the background. + // See http://crbug.com/469890. + removeSyncStateChangedListener(); + } + private void addSyncStateChangedListener() { - if (sSyncStateChangedListener != null) { + if (mSyncStateChangedListener != null) { return; } - sSyncStateChangedListener = new ProfileSyncService.SyncStateChangedListener() { + mSyncStateChangedListener = new ProfileSyncService.SyncStateChangedListener() { @Override public void syncStateChanged() { if (ProfileSyncService.get(getApplicationContext()).isSyncInitialized()) { @@ -84,12 +93,14 @@ } } }; - ProfileSyncService.get(this).addSyncStateChangedListener(sSyncStateChangedListener); + ProfileSyncService.get(this).addSyncStateChangedListener(mSyncStateChangedListener); } private void removeSyncStateChangedListener() { - ProfileSyncService.get(this).removeSyncStateChangedListener(sSyncStateChangedListener); - sSyncStateChangedListener = null; + if (mSyncStateChangedListener != null) { + ProfileSyncService.get(this).removeSyncStateChangedListener(mSyncStateChangedListener); + mSyncStateChangedListener = null; + } } private boolean isShowingDialog(String tag) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FakeProfileSyncService.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FakeProfileSyncService.java new file mode 100644 index 0000000..46ba2ccd --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FakeProfileSyncService.java
@@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.sync; + +import android.content.Context; + +/** + * Fake some ProfileSyncService methods for testing. + * + * Only what has been needed for tests so far has been faked. + */ +public class FakeProfileSyncService extends ProfileSyncService { + + private boolean mBackendInitialized; + + public FakeProfileSyncService(Context context) { + super(context); + } + + @Override + public boolean isSyncInitialized() { + return mBackendInitialized; + } + + public void setSyncInitialized(boolean syncInitialized) { + mBackendInitialized = syncInitialized; + } + + @Override + public boolean isUsingSecondaryPassphrase() { + return true; + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java new file mode 100644 index 0000000..8498da16 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
@@ -0,0 +1,94 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.sync.ui; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.sync.FakeProfileSyncService; +import org.chromium.chrome.browser.sync.ProfileSyncService; +import org.chromium.chrome.shell.ChromeShellTestBase; +import org.chromium.sync.signin.ChromeSigninController; + +/** + * Tests for PassphraseActivity. + */ +public class PassphraseActivityTest extends ChromeShellTestBase { + private static final String TAG = "PassphraseActivityTest"; + private static final String TEST_ACCOUNT = "test@gmail.com"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + clearAppData(); + Context context = getInstrumentation().getTargetContext(); + startChromeBrowserProcessSync(context); + } + + @Override + protected void tearDown() throws Exception { + // Clear ProfileSyncService in case it was mocked. + ProfileSyncService.overrideForTests(null); + super.tearDown(); + } + + /** + * This is a regression test for http://crbug.com/469890. + */ + @SmallTest + @Feature({"Sync"}) + public void testCallbackAfterBackgrounded() throws Exception { + final Context context = getInstrumentation().getTargetContext(); + // Override before creating the activity so we know initialized is false. + overrideProfileSyncService(context); + // PassphraseActivity won't start if an account isn't set. + ChromeSigninController.get(context).setSignedInAccountName(TEST_ACCOUNT); + // Create the activity. + final PassphraseActivity activity = launchPassphraseActivity(context); + assertNotNull(activity); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + // Fake backgrounding the activity. + Bundle bundle = new Bundle(); + getInstrumentation().callActivityOnPause(activity); + getInstrumentation().callActivityOnSaveInstanceState(activity, bundle); + // Fake sync's backend finishing its initialization. + FakeProfileSyncService pss = + (FakeProfileSyncService) ProfileSyncService.get(context); + pss.setSyncInitialized(true); + pss.syncStateChanged(); + } + }); + // Nothing crashed; success! + } + + private PassphraseActivity launchPassphraseActivity(Context context) { + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setComponent(new ComponentName(context, PassphraseActivity.class)); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + // This activity will become the start of a new task on this history stack. + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // Clears the task stack above this activity if it already exists. + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + return launchActivityWithIntent( + "org.chromium.chrome.shell", PassphraseActivity.class, intent); + } + + private void overrideProfileSyncService(final Context context) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + // PSS has to be constructed on the UI thread. + ProfileSyncService.overrideForTests(new FakeProfileSyncService(context)); + } + }); + } +}
diff --git a/chrome/android/shell/java/AndroidManifest.xml.jinja2 b/chrome/android/shell/java/AndroidManifest.xml.jinja2 index 212b264..d160d7c 100644 --- a/chrome/android/shell/java/AndroidManifest.xml.jinja2 +++ b/chrome/android/shell/java/AndroidManifest.xml.jinja2
@@ -65,6 +65,9 @@ android:label="@string/preferences" android:exported="false"> </activity> + <activity android:name="org.chromium.chrome.browser.sync.ui.PassphraseActivity" + android:theme="@style/PreferencesTheme"> + </activity> <!-- The following service entries exist in order to allow us to start more than one sandboxed process. -->
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellApplication.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellApplication.java index c99e84e9..05f0756 100644 --- a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellApplication.java +++ b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellApplication.java
@@ -10,11 +10,12 @@ import org.chromium.base.PathUtils; import org.chromium.base.ResourceExtractor; import org.chromium.chrome.browser.ChromiumApplication; -import org.chromium.chrome.browser.PKCS11AuthenticationManager; import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.browser.invalidation.UniqueIdInvalidationClientNameGenerator; import org.chromium.chrome.browser.metrics.UmaUtils; +import org.chromium.chrome.browser.smartcard.EmptyPKCS11AuthenticationManager; +import org.chromium.chrome.browser.smartcard.PKCS11AuthenticationManager; import org.chromium.chrome.browser.sync.SyncController; import org.chromium.chrome.shell.preferences.ChromeShellPreferences; @@ -115,6 +116,6 @@ @Override protected PKCS11AuthenticationManager getPKCS11AuthenticationManager() { - return new ChromeShellPKCS11AuthenticationManager(); + return EmptyPKCS11AuthenticationManager.getInstance(); } }
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellPKCS11AuthenticationManager.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellPKCS11AuthenticationManager.java deleted file mode 100644 index 6a8ae55..0000000 --- a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellPKCS11AuthenticationManager.java +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.shell; - -import android.content.Context; - -import org.chromium.chrome.browser.PKCS11AuthenticationManager; -import org.chromium.net.AndroidPrivateKey; - -import java.security.cert.X509Certificate; - -/** - * ChromeShell stub implementation of PKCS11AuthenticationManager. - */ -public class ChromeShellPKCS11AuthenticationManager implements PKCS11AuthenticationManager { - @Override - public boolean isPKCS11AuthEnabled() { - return false; - } - - @Override - public String getClientCertificateAlias(String hostName, int port) { - return null; - } - - @Override - public void initialize(Context context) { - } - - - @Override - public X509Certificate[] getCertificateChain(String alias) { - return null; - } - - @Override - public AndroidPrivateKey getPrivateKey(String alias) { - return null; - } -}
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 31929e0..a93410f 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -14,7 +14,7 @@ Chromebase </message> <message name="IDS_CHROMEBIT" desc="The localized name for Chromebit"> - Chromebit + Chromebit </message> <!-- Idle logout dialog for retail mode --> <message name="IDS_IDLE_LOGOUT_TITLE" desc="Dialog title for the idle logout dialog. Used in retail mode only."> @@ -1623,6 +1623,12 @@ <message name="IDS_BROWSE_WITHOUT_SIGNING_IN_BUTTON"> Skip sign-in and browse as Guest </message> + <message name="IDS_WHITELIST_ERROR_TRY_AGAIN_BUTTON" desc="The text of the try again button on the whitelist error UI."> + Try again + </message> + <message name="IDS_WHITELIST_ERROR_LEARN_MORE_BUTTON" desc="The text of the learn more link on the whitelist error UI."> + Learn more + </message> <message name="IDS_CREATE_ACCOUNT_HTML" desc="Text shown on side of Google sign-in UI."> If you don't have a Google Account you can <ph name="LINK_START">$1<ex>>a<</ex></ph>create a Google Account<ph name="LINK_END">$2<ex>>/a<</ex></ph> now. </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f828c23..76a06f9 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -48,7 +48,7 @@ } } -static_library("browser") { +source_set("browser") { configs += [ "//build/config/compiler:wexit_time_destructors", "//third_party/WebKit/public:debug_devtools", @@ -682,7 +682,10 @@ "//ui/metro_viewer", "//win8:metro_viewer", ] - libs += [ "credui.lib" ] + libs += [ + "credui.lib", + "netapi32.lib", + ] } else { # Non-Windows. sources +=
diff --git a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm index a17fb010..1382dd5 100644 --- a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm +++ b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm
@@ -265,10 +265,11 @@ base::FilePath GetAppShimPath(Profile* profile, const extensions::Extension* app) { // Use a WebAppShortcutCreator to get the path. + scoped_ptr<web_app::ShortcutInfo> shortcut_info = + web_app::ShortcutInfoForExtensionAndProfile(app, profile); web_app::WebAppShortcutCreator shortcut_creator( web_app::GetWebAppDataDirectory(profile->GetPath(), app->id(), GURL()), - web_app::ShortcutInfoForExtensionAndProfile(app, profile), - extensions::FileHandlersInfo()); + shortcut_info.get(), extensions::FileHandlersInfo()); return shortcut_creator.GetInternalShortcutPath(); } @@ -649,10 +650,11 @@ const extensions::Extension* app = InstallPlatformApp("minimal"); // Use WebAppShortcutCreator to create a 64 bit shim. + scoped_ptr<web_app::ShortcutInfo> shortcut_info = + web_app::ShortcutInfoForExtensionAndProfile(app, profile()); web_app::WebAppShortcutCreator shortcut_creator( web_app::GetWebAppDataDirectory(profile()->GetPath(), app->id(), GURL()), - web_app::ShortcutInfoForExtensionAndProfile(app, profile()), - extensions::FileHandlersInfo()); + shortcut_info.get(), extensions::FileHandlersInfo()); shortcut_creator.UpdateShortcuts(); base::FilePath shim_path = shortcut_creator.GetInternalShortcutPath(); NSMutableDictionary* plist_64 = [NSMutableDictionary
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 9b82907..5172935 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -981,15 +981,8 @@ } // This test is disabled due to being flaky. http://crbug.com/282116 -#if defined(OS_WIN) || defined(OS_MACOSX) -#define MAYBE_Shim_TestAutosizeWithPartialAttributes \ - DISABLED_Shim_TestAutosizeWithPartialAttributes -#else -#define MAYBE_Shim_TestAutosizeWithPartialAttributes \ - Shim_TestAutosizeWithPartialAttributes -#endif IN_PROC_BROWSER_TEST_F(WebViewTest, - MAYBE_Shim_TestAutosizeWithPartialAttributes) { + DISABLED_Shim_TestAutosizeWithPartialAttributes) { TestHelper("testAutosizeWithPartialAttributes", "web_view/shim", NO_TEST_SERVER); @@ -2737,3 +2730,15 @@ ASSERT_TRUE(RunExtensionTest("platform_apps/web_view/background")) << message_; } + +// This test verifies that the allowtransparency attribute properly propagates +IN_PROC_BROWSER_TEST_F(WebViewTest, AllowTransparencyAndAllowScalingPropagate) { + LoadAppWithGuest("web_view/simple"); + + ASSERT_TRUE(!!GetGuestWebContents()); + extensions::WebViewGuest* guest = + extensions::WebViewGuest::FromWebContents(GetGuestWebContents()); + ASSERT_TRUE(guest->allow_transparency()); + ASSERT_TRUE(guest->allow_scaling()); +} +
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 5e3d4ef..c250470 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -1176,6 +1176,13 @@ #endif // defined(OS_WIN) if (parsed_command_line().HasSwitch(switches::kMakeDefaultBrowser)) { + bool is_managed = g_browser_process->local_state()->IsManagedPreference( + prefs::kDefaultBrowserSettingEnabled); + if (is_managed && !g_browser_process->local_state()->GetBoolean( + prefs::kDefaultBrowserSettingEnabled)) { + return static_cast<int>(chrome::RESULT_CODE_ACTION_DISALLOWED_BY_POLICY); + } + return ShellIntegration::SetAsDefaultBrowser() ? static_cast<int>(content::RESULT_CODE_NORMAL_EXIT) : static_cast<int>(chrome::RESULT_CODE_SHELL_INTEGRATION_FAILED);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc index c4e419551..1b71ef0 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -182,9 +182,25 @@ new std::string(volume.source_path().AsUTF8Unsafe())); } + switch (volume.volume_source()) { + case VOLUME_SOURCE_UNKNOWN: + volume_metadata->volume_source = file_manager_private::VOLUME_SOURCE_NONE; + break; + case VOLUME_SOURCE_FILE: + volume_metadata->volume_source = file_manager_private::VOLUME_SOURCE_FILE; + break; + case VOLUME_SOURCE_DEVICE: + volume_metadata->volume_source = + file_manager_private::VOLUME_SOURCE_DEVICE; + break; + case VOLUME_SOURCE_NETWORK: + volume_metadata->volume_source = + file_manager_private::VOLUME_SOURCE_NETWORK; + break; + } + if (volume.type() == VOLUME_TYPE_PROVIDED) { volume_metadata->extension_id.reset(new std::string(volume.extension_id())); - volume_metadata->file_system_id.reset( new std::string(volume.file_system_id())); }
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc index 09a89207..643bb3d 100644 --- a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc +++ b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc
@@ -70,6 +70,22 @@ return results; } +// Converts the file system source from the IDL type to a native type. +chromeos::file_system_provider::Source ParseSource( + const api::file_system_provider::FileSystemSource& source) { + switch (source) { + case api::file_system_provider::FILE_SYSTEM_SOURCE_FILE: + return chromeos::file_system_provider::SOURCE_FILE; + case api::file_system_provider::FILE_SYSTEM_SOURCE_DEVICE: + return chromeos::file_system_provider::SOURCE_DEVICE; + case api::file_system_provider::FILE_SYSTEM_SOURCE_NETWORK: + return chromeos::file_system_provider::SOURCE_NETWORK; + case api::file_system_provider::FILE_SYSTEM_SOURCE_NONE: + return chromeos::file_system_provider::SOURCE_UNKNOWN; + } + return chromeos::file_system_provider::SOURCE_UNKNOWN; +} + // Fills the IDL's FileSystemInfo with FSP's ProvidedFileSystemInfo and // Watchers. void FillFileSystemInfo(const ProvidedFileSystemInfo& file_system_info, @@ -83,6 +99,20 @@ output->display_name = file_system_info.display_name(); output->writable = file_system_info.writable(); output->opened_files_limit = file_system_info.opened_files_limit(); + switch (file_system_info.source()) { + case chromeos::file_system_provider::SOURCE_FILE: + output->source = api::file_system_provider::FILE_SYSTEM_SOURCE_FILE; + break; + case chromeos::file_system_provider::SOURCE_DEVICE: + output->source = api::file_system_provider::FILE_SYSTEM_SOURCE_DEVICE; + break; + case chromeos::file_system_provider::SOURCE_NETWORK: + output->source = api::file_system_provider::FILE_SYSTEM_SOURCE_NETWORK; + break; + case chromeos::file_system_provider::SOURCE_UNKNOWN: + output->source = api::file_system_provider::FILE_SYSTEM_SOURCE_NONE; + break; + } std::vector<linked_ptr<Watcher>> watcher_items; for (const auto& watcher : watchers) { @@ -152,6 +182,7 @@ ? *params->options.opened_files_limit.get() : 0; options.supports_notify_tag = params->options.supports_notify_tag; + options.source = ParseSource(params->options.source); const base::File::Error result = service->MountFileSystem(extension_id(), options);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 43a3d0c..5a25000 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -830,7 +830,10 @@ ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDownloads"), TestParameter(IN_GUEST_MODE, "fileDisplayDownloads"), TestParameter(NOT_IN_GUEST_MODE, "fileDisplayDrive"), - TestParameter(NOT_IN_GUEST_MODE, "fileDisplayMtp"))); + TestParameter(NOT_IN_GUEST_MODE, "fileDisplayMtp"), + TestParameter(NOT_IN_GUEST_MODE, "searchNormal"), + TestParameter(NOT_IN_GUEST_MODE, "searchCaseInsensitive"), + TestParameter(NOT_IN_GUEST_MODE, "searchNotFound"))); // Slow tests are disabled on debug build. http://crbug.com/327719 // Fails on official build. http://crbug.com/429294
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc index b41b65e..227cdc02 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.cc +++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -150,6 +150,7 @@ volume->type_ = VOLUME_TYPE_GOOGLE_DRIVE; volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN; volume->source_path_ = drive_path; + volume->volume_source_ = VOLUME_SOURCE_NETWORK; volume->mount_path_ = drive_path; volume->mount_condition_ = chromeos::disks::MOUNT_CONDITION_NONE; volume->is_parent_ = false; @@ -165,6 +166,7 @@ volume->type_ = VOLUME_TYPE_DOWNLOADS_DIRECTORY; volume->device_type_ = chromeos::DEVICE_TYPE_UNKNOWN; // Keep source_path empty. + volume->volume_source_ = VOLUME_SOURCE_DEVICE; volume->mount_path_ = downloads_path; volume->mount_condition_ = chromeos::disks::MOUNT_CONDITION_NONE; volume->is_parent_ = false; @@ -181,6 +183,10 @@ Volume* const volume = new Volume; volume->type_ = MountTypeToVolumeType(mount_point.mount_type); volume->source_path_ = base::FilePath(mount_point.source_path); + volume->volume_source_ = + mount_point.mount_type == chromeos::MOUNT_TYPE_ARCHIVE + ? VOLUME_SOURCE_FILE + : VOLUME_SOURCE_DEVICE; volume->mount_path_ = base::FilePath(mount_point.mount_path); volume->mount_condition_ = mount_point.mount_condition; volume->volume_label_ = volume->mount_path().BaseName().AsUTF8Unsafe(); @@ -209,6 +215,20 @@ Volume* const volume = new Volume; volume->file_system_id_ = file_system_info.file_system_id(); volume->extension_id_ = file_system_info.extension_id(); + switch (file_system_info.source()) { + case chromeos::file_system_provider::SOURCE_UNKNOWN: + volume->volume_source_ = VOLUME_SOURCE_UNKNOWN; + break; + case chromeos::file_system_provider::SOURCE_FILE: + volume->volume_source_ = VOLUME_SOURCE_FILE; + break; + case chromeos::file_system_provider::SOURCE_DEVICE: + volume->volume_source_ = VOLUME_SOURCE_DEVICE; + break; + case chromeos::file_system_provider::SOURCE_NETWORK: + volume->volume_source_ = VOLUME_SOURCE_NETWORK; + break; + } volume->volume_label_ = file_system_info.display_name(); volume->type_ = VOLUME_TYPE_PROVIDED; volume->mount_path_ = file_system_info.mount_path(); @@ -234,6 +254,7 @@ volume->volume_id_ = kMtpVolumeIdPrefix + label; volume->volume_label_ = label; volume->source_path_ = mount_path; + volume->volume_source_ = VOLUME_SOURCE_DEVICE; volume->device_type_ = chromeos::DEVICE_TYPE_MOBILE; return volume; } @@ -247,6 +268,7 @@ volume->type_ = volume_type; volume->device_type_ = device_type; // Keep source_path empty. + volume->volume_source_ = VOLUME_SOURCE_DEVICE; volume->mount_path_ = path; volume->mount_condition_ = chromeos::disks::MOUNT_CONDITION_NONE; volume->is_parent_ = false;
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h index efaf20f..9b7aef6 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.h +++ b/chrome/browser/chromeos/file_manager/volume_manager.h
@@ -57,6 +57,14 @@ NUM_VOLUME_TYPE, }; +// Source of a volume's data. +enum VolumeSource { + VOLUME_SOURCE_UNKNOWN, + VOLUME_SOURCE_FILE, + VOLUME_SOURCE_DEVICE, + VOLUME_SOURCE_NETWORK +}; + // Says how was the mount performed, whether due to user interaction, or // automatic. User interaction includes both hardware (pluggins a USB stick) // or software (mounting a ZIP archive) interaction. @@ -97,6 +105,7 @@ const std::string& volume_id() const { return volume_id_; } const std::string& file_system_id() const { return file_system_id_; } const std::string& extension_id() const { return extension_id_; } + const VolumeSource volume_source() const { return volume_source_; } VolumeType type() const { return type_; } chromeos::DeviceType device_type() const { return device_type_; } const base::FilePath& source_path() const { return source_path_; } @@ -127,6 +136,9 @@ // to an empty string. std::string extension_id_; + // The source of the file system's data. + VolumeSource volume_source_; + // The type of mounted volume. VolumeType type_;
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc index 38dc4a5..e09e780 100644 --- a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc +++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.cc
@@ -9,7 +9,10 @@ namespace file_system_provider { MountOptions::MountOptions() - : writable(false), supports_notify_tag(false), opened_files_limit(0) { + : writable(false), + source(SOURCE_UNKNOWN), + supports_notify_tag(false), + opened_files_limit(0) { } MountOptions::MountOptions(const std::string& file_system_id, @@ -17,12 +20,13 @@ : file_system_id(file_system_id), display_name(display_name), writable(false), + source(SOURCE_UNKNOWN), supports_notify_tag(false), opened_files_limit(0) { } ProvidedFileSystemInfo::ProvidedFileSystemInfo() - : writable_(false), supports_notify_tag_(false) { + : writable_(false), source_(SOURCE_UNKNOWN), supports_notify_tag_(false) { } ProvidedFileSystemInfo::ProvidedFileSystemInfo( @@ -33,6 +37,7 @@ file_system_id_(mount_options.file_system_id), display_name_(mount_options.display_name), writable_(mount_options.writable), + source_(mount_options.source), supports_notify_tag_(mount_options.supports_notify_tag), opened_files_limit_(mount_options.opened_files_limit), mount_path_(mount_path) {
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h index 795577ce..53a610f 100644 --- a/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h +++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_info.h
@@ -12,6 +12,9 @@ namespace chromeos { namespace file_system_provider { +// Source of the file system's contents. +enum Source { SOURCE_UNKNOWN, SOURCE_FILE, SOURCE_DEVICE, SOURCE_NETWORK }; + // Options for creating the provided file system info. struct MountOptions { MountOptions(); @@ -23,6 +26,7 @@ std::string file_system_id; std::string display_name; bool writable; + Source source; bool supports_notify_tag; int opened_files_limit; }; @@ -42,6 +46,7 @@ const std::string& file_system_id() const { return file_system_id_; } const std::string& display_name() const { return display_name_; } bool writable() const { return writable_; } + Source source() const { return source_; } bool supports_notify_tag() const { return supports_notify_tag_; } int opened_files_limit() const { return opened_files_limit_; } const base::FilePath& mount_path() const { return mount_path_; } @@ -59,6 +64,9 @@ // Whether the file system is writable or just read-only. bool writable_; + // Source of the file system's contents. By default SOURCE_UNKNOWN. + Source source_; + // Supports tags for file/directory change notifications. bool supports_notify_tag_;
diff --git a/chrome/browser/chromeos/file_system_provider/registry.cc b/chrome/browser/chromeos/file_system_provider/registry.cc index c0bf95d3..f3b3cd7 100644 --- a/chrome/browser/chromeos/file_system_provider/registry.cc +++ b/chrome/browser/chromeos/file_system_provider/registry.cc
@@ -26,6 +26,7 @@ const char kPrefKeyFileSystemId[] = "file-system-id"; const char kPrefKeyDisplayName[] = "display-name"; const char kPrefKeyWritable[] = "writable"; +const char kPrefKeySource[] = "source"; const char kPrefKeySupportsNotifyTag[] = "supports-notify-tag"; const char kPrefKeyWatchers[] = "watchers"; const char kPrefKeyWatcherEntryPath[] = "entry-path"; @@ -40,6 +41,41 @@ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); } +std::string SourceToString(Source source) { + switch (source) { + case SOURCE_UNKNOWN: + return "unknown"; + case SOURCE_FILE: + return "file"; + case SOURCE_DEVICE: + return "device"; + case SOURCE_NETWORK: + return "network"; + } + NOTREACHED(); + return std::string(); +} + +bool StringToSource(const std::string& source, Source* result) { + if (source.compare("unknown") == 0) { + *result = SOURCE_UNKNOWN; + return true; + } + if (source.compare("file") == 0) { + *result = SOURCE_FILE; + return true; + } + if (source.compare("device") == 0) { + *result = SOURCE_DEVICE; + return true; + } + if (source.compare("network") == 0) { + *result = SOURCE_NETWORK; + return true; + } + return false; +} + Registry::Registry(Profile* profile) : profile_(profile) { } @@ -56,6 +92,8 @@ file_system_info.display_name()); file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable, file_system_info.writable()); + file_system->SetStringWithoutPathExpansion( + kPrefKeySource, SourceToString(file_system_info.source())); file_system->SetBooleanWithoutPathExpansion( kPrefKeySupportsNotifyTag, file_system_info.supports_notify_tag()); file_system->SetIntegerWithoutPathExpansion( @@ -153,6 +191,8 @@ bool writable = false; bool supports_notify_tag = false; int opened_files_limit = 0; + std::string source_as_string; + Source source = SOURCE_UNKNOWN; // TODO(mtomasz): Move opened files limit to the mandatory list above in // M42. @@ -166,9 +206,12 @@ !file_system->GetBooleanWithoutPathExpansion(kPrefKeySupportsNotifyTag, &supports_notify_tag) || file_system_id.empty() || display_name.empty()) || + // Optional fields. (file_system->GetIntegerWithoutPathExpansion(kPrefKeyOpenedFilesLimit, &opened_files_limit) && - opened_files_limit < 0)) { + (file_system->GetStringWithoutPathExpansion(kPrefKeySource, + &source_as_string) && + !StringToSource(source_as_string, &source)))) { LOG(ERROR) << "Malformed provided file system information in preferences."; continue; @@ -178,6 +221,7 @@ options.file_system_id = file_system_id; options.display_name = display_name; options.writable = writable; + options.source = source; options.supports_notify_tag = supports_notify_tag; options.opened_files_limit = opened_files_limit;
diff --git a/chrome/browser/chromeos/file_system_provider/registry.h b/chrome/browser/chromeos/file_system_provider/registry.h index 0483e45..9072905 100644 --- a/chrome/browser/chromeos/file_system_provider/registry.h +++ b/chrome/browser/chromeos/file_system_provider/registry.h
@@ -24,6 +24,7 @@ extern const char kPrefKeyFileSystemId[]; extern const char kPrefKeyDisplayName[]; extern const char kPrefKeyWritable[]; +extern const char kPrefKeySource[]; extern const char kPrefKeySupportsNotifyTag[]; extern const char kPrefKeyWatchers[]; extern const char kPrefKeyWatcherEntryPath[]; @@ -37,6 +38,11 @@ // Registers preferences to remember registered file systems between reboots. void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); +// Converts a file system's data source value back and forth between Source and +// std::string types. +std::string SourceToString(Source source); +bool StringToSource(const std::string& source, Source* result); + // Remembers and restores file systems in a persistent storage. class Registry : public RegistryInterface { public:
diff --git a/chrome/browser/chromeos/file_system_provider/registry_unittest.cc b/chrome/browser/chromeos/file_system_provider/registry_unittest.cc index b02359f..8d58371 100644 --- a/chrome/browser/chromeos/file_system_provider/registry_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/registry_unittest.cc
@@ -29,6 +29,7 @@ "chrome-extension://efgefgefgefgefgefgefgefgefgefgefgefge/"; const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj"; const char kDisplayName[] = "Camera Pictures"; +const Source kSource = SOURCE_NETWORK; // The dot in the file system ID is there in order to check that saving to // preferences works correctly. File System ID is used as a key in @@ -44,6 +45,7 @@ const std::string& file_system_id, const std::string& display_name, bool writable, + Source source, bool supports_notify_tag, int opened_files_limit, const Watcher& watcher) { @@ -60,6 +62,8 @@ kFileSystemId); file_system->SetStringWithoutPathExpansion(kPrefKeyDisplayName, kDisplayName); file_system->SetBooleanWithoutPathExpansion(kPrefKeyWritable, writable); + file_system->SetStringWithoutPathExpansion(kPrefKeySource, + SourceToString(source)); file_system->SetBooleanWithoutPathExpansion(kPrefKeySupportsNotifyTag, supports_notify_tag); file_system->SetIntegerWithoutPathExpansion(kPrefKeyOpenedFilesLimit, @@ -124,8 +128,9 @@ TEST_F(FileSystemProviderRegistryTest, RestoreFileSystems) { // Create a fake entry in the preferences. RememberFakeFileSystem(profile_, kExtensionId, kFileSystemId, kDisplayName, - true /* writable */, true /* supports_notify_tag */, - kOpenedFilesLimit, fake_watcher_); + true /* writable */, kSource, + true /* supports_notify_tag */, kOpenedFilesLimit, + fake_watcher_); scoped_ptr<RegistryInterface::RestoredFileSystems> restored_file_systems = registry_->RestoreFileSystems(kExtensionId); @@ -137,6 +142,7 @@ EXPECT_EQ(kFileSystemId, restored_file_system.options.file_system_id); EXPECT_EQ(kDisplayName, restored_file_system.options.display_name); EXPECT_TRUE(restored_file_system.options.writable); + EXPECT_EQ(kSource, restored_file_system.options.source); EXPECT_TRUE(restored_file_system.options.supports_notify_tag); EXPECT_EQ(kOpenedFilesLimit, restored_file_system.options.opened_files_limit); @@ -153,6 +159,7 @@ TEST_F(FileSystemProviderRegistryTest, RememberFileSystem) { MountOptions options(kFileSystemId, kDisplayName); options.writable = true; + options.source = kSource; options.supports_notify_tag = true; options.opened_files_limit = kOpenedFilesLimit; @@ -199,6 +206,11 @@ file_system->GetBooleanWithoutPathExpansion(kPrefKeyWritable, &writable)); EXPECT_TRUE(writable); + std::string source_as_string; + EXPECT_TRUE(file_system->GetStringWithoutPathExpansion(kPrefKeySource, + &source_as_string)); + EXPECT_EQ("network", source_as_string); + bool supports_notify_tag = false; EXPECT_TRUE(file_system->GetBooleanWithoutPathExpansion( kPrefKeySupportsNotifyTag, &supports_notify_tag)); @@ -248,8 +260,9 @@ TEST_F(FileSystemProviderRegistryTest, ForgetFileSystem) { // Create a fake file systems in the preferences. RememberFakeFileSystem(profile_, kExtensionId, kFileSystemId, kDisplayName, - true /* writable */, true /* supports_notify_tag */, - kOpenedFilesLimit, fake_watcher_); + true /* writable */, kSource, + true /* supports_notify_tag */, kOpenedFilesLimit, + fake_watcher_); registry_->ForgetFileSystem(kExtensionId, kFileSystemId); @@ -316,5 +329,28 @@ EXPECT_EQ(fake_watcher_.last_tag, last_tag); } +TEST_F(FileSystemProviderRegistryTest, SourceToString) { + { + Source result = SOURCE_UNKNOWN; + EXPECT_TRUE(StringToSource(SourceToString(SOURCE_FILE), &result)); + EXPECT_EQ(SOURCE_FILE, result); + } + { + Source result = SOURCE_UNKNOWN; + EXPECT_TRUE(StringToSource(SourceToString(SOURCE_DEVICE), &result)); + EXPECT_EQ(SOURCE_DEVICE, result); + } + { + Source result = SOURCE_UNKNOWN; + EXPECT_TRUE(StringToSource(SourceToString(SOURCE_NETWORK), &result)); + EXPECT_EQ(SOURCE_NETWORK, result); + } + { + Source result = SOURCE_FILE; + EXPECT_TRUE(StringToSource(SourceToString(SOURCE_UNKNOWN), &result)); + EXPECT_EQ(SOURCE_UNKNOWN, result); + } +} + } // namespace file_system_provider } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.cc b/chrome/browser/chromeos/login/app_launch_signin_screen.cc index 9056358a..d98d51b 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.cc +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
@@ -184,10 +184,8 @@ LOG(ERROR) << "Unlock failure: " << error.reason(); webui_handler_->ClearAndEnablePassword(); webui_handler_->ShowError( - 0, - l10n_util::GetStringUTF8(IDS_LOGIN_ERROR_AUTHENTICATING_KIOSK), - std::string(), - HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE); + 0, l10n_util::GetStringUTF8(IDS_LOGIN_ERROR_AUTHENTICATING_KIOSK), + std::string(), HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); } void AppLaunchSigninScreen::OnAuthSuccess(const UserContext& user_context) {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc index 6c47ed7..e5a42fb0 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc
@@ -17,7 +17,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/login/auth/key.h" -#include "components/proximity_auth/base64url.h" +#include "components/proximity_auth/cryptauth/base64url.h" #include "crypto/encryptor.h" #include "crypto/random.h" #include "crypto/symmetric_key.h"
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index b71cc1d..ce08f36 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -691,18 +691,18 @@ PerformLoginFinishedActions(true /* start public session timer */); offline_failed_ = false; - if (g_browser_process->platform_part() - ->browser_policy_connector_chromeos() - ->IsEnterpriseManaged()) { - ShowError(IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST, email); + if (StartupUtils::IsWebviewSigninEnabled()) { + login_display_->ShowWhitelistCheckFailedError(); } else { - ShowError(IDS_LOGIN_ERROR_WHITELIST, email); - } - - if (StartupUtils::IsWebviewSigninEnabled()) - login_display_->ShowSigninUI(""); - else + if (g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->IsEnterpriseManaged()) { + ShowError(IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST, email); + } else { + ShowError(IDS_LOGIN_ERROR_WHITELIST, email); + } login_display_->ShowSigninUI(email); + } if (auth_status_consumer_) { auth_status_consumer_->OnAuthFailure( @@ -941,17 +941,9 @@ void ExistingUserController::ShowError(int error_id, const std::string& details) { - // TODO(dpolukhin): show detailed error info. |details| string contains - // low level error info that is not localized and even is not user friendly. - // For now just ignore it because error_text contains all required information - // for end users, developers can see details string in Chrome logs. VLOG(1) << details; HelpAppLauncher::HelpTopic help_topic_id; - bool is_offline = !network_state_helper_->IsConnected(); switch (login_performer_->error().state()) { - case GoogleServiceAuthError::CONNECTION_FAILED: - help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE; - break; case GoogleServiceAuthError::ACCOUNT_DISABLED: help_topic_id = HelpAppLauncher::HELP_ACCOUNT_DISABLED; break; @@ -959,9 +951,7 @@ help_topic_id = HelpAppLauncher::HELP_HOSTED_ACCOUNT; break; default: - help_topic_id = is_offline ? - HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE : - HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT; + help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT; break; }
diff --git a/chrome/browser/chromeos/login/help_app_launcher.h b/chrome/browser/chromeos/login/help_app_launcher.h index 33d769a..2be8f92 100644 --- a/chrome/browser/chromeos/login/help_app_launcher.h +++ b/chrome/browser/chromeos/login/help_app_launcher.h
@@ -26,9 +26,7 @@ HELP_CONNECTIVITY = 188752, // Showed at EULA screen as "Learn more" about stats/crash reports. HELP_STATS_USAGE = 183078, - // Showed whenever there're troubles signing in (offline case). - HELP_CANT_ACCESS_ACCOUNT_OFFLINE = 188755, - // Showed whenever there're troubles signing in (online case). + // Showed whenever there're troubles signing in. HELP_CANT_ACCESS_ACCOUNT = 188036, // Showed in case when account was disabled. HELP_ACCOUNT_DISABLED = 188756,
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 95b0af5..0a11e4cf 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/test/https_forwarder.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" #include "chrome/browser/chromeos/login/ui/webui_login_display.h" @@ -36,7 +37,6 @@ #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/policy/test/local_policy_test_server.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/signin/inline_login_ui.h" @@ -259,140 +259,35 @@ } // namespace -class SamlTest : public InProcessBrowserTest, - public testing::WithParamInterface<bool> { +class SamlTest : public OobeBaseTest, public testing::WithParamInterface<bool> { public: - SamlTest() : gaia_frame_parent_("signin-frame"), saml_load_injected_(false) {} + SamlTest() : saml_load_injected_(false) { use_webview_ = GetParam(); } ~SamlTest() override {} - bool UseWebView() const { - return GetParam(); - } - - void SetUp() override { - ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); - - // Start the GAIA https wrapper here so that the GAIA URLs can be pointed at - // it in SetUpCommandLine(). - gaia_https_forwarder_.reset( - new HTTPSForwarder(embedded_test_server()->base_url())); - ASSERT_TRUE(gaia_https_forwarder_->Start()); - - // Start the SAML IdP https wrapper here so that GAIA can be pointed at it - // in SetUpCommandLine(). - saml_https_forwarder_.reset( - new HTTPSForwarder(embedded_test_server()->base_url())); - ASSERT_TRUE(saml_https_forwarder_->Start()); - - // Stop IO thread here because no threads are allowed while - // spawning sandbox host process. See crbug.com/322732. - embedded_test_server()->StopThread(); - - InProcessBrowserTest::SetUp(); - } - - bool SetUpUserDataDirectory() override { - if (UseWebView()) { - // Fake Dev channel to enable webview signin. - scoped_channel_.reset(new extensions::ScopedCurrentChannel( - chrome::VersionInfo::CHANNEL_DEV)); - - base::FilePath user_data_dir; - CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); - base::FilePath local_state_path = - user_data_dir.Append(chrome::kLocalStateFilename); - - // Set webview enabled flag only when local state file does not exist. - // Otherwise, we break PRE tests that leave state in it. - if (!base::PathExists(local_state_path)) { - base::DictionaryValue local_state_dict; - local_state_dict.SetBoolean(prefs::kWebviewSigninEnabled, true); - // OobeCompleted to skip controller-pairing-screen which still uses - // iframe and ends up in a JS error in oobe page init. - // See http://crbug.com/467147 - local_state_dict.SetBoolean(prefs::kOobeComplete, true); - - CHECK(JSONFileValueSerializer(local_state_path) - .Serialize(local_state_dict)); - } - } - - return InProcessBrowserTest::SetUpUserDataDirectory(); - } - - void SetUpInProcessBrowserTestFixture() override { - host_resolver()->AddRule("*", "127.0.0.1"); - } - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kLoginManager); - command_line->AppendSwitch(switches::kForceLoginManagerInTests); command_line->AppendSwitch(switches::kOobeSkipPostLogin); - command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); - command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); const GURL gaia_url = gaia_https_forwarder_->GetURL(""); - command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec()); - command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec()); - command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, - gaia_url.spec()); - const GURL saml_idp_url = saml_https_forwarder_->GetURL("SAML"); fake_saml_idp_.SetUp(saml_idp_url.path(), gaia_url); - fake_gaia_.RegisterSamlUser(kFirstSAMLUserEmail, saml_idp_url); - fake_gaia_.RegisterSamlUser(kSecondSAMLUserEmail, saml_idp_url); - fake_gaia_.RegisterSamlUser( + fake_gaia_->RegisterSamlUser(kFirstSAMLUserEmail, saml_idp_url); + fake_gaia_->RegisterSamlUser(kSecondSAMLUserEmail, saml_idp_url); + fake_gaia_->RegisterSamlUser( kHTTPSAMLUserEmail, embedded_test_server()->base_url().Resolve("/SAML")); - fake_gaia_.RegisterSamlUser(kDifferentDomainSAMLUserEmail, saml_idp_url); + fake_gaia_->RegisterSamlUser(kDifferentDomainSAMLUserEmail, saml_idp_url); - fake_gaia_.Initialize(); - fake_gaia_.set_issue_oauth_code_cookie(UseWebView()); + OobeBaseTest::SetUpCommandLine(command_line); } void SetUpOnMainThread() override { - fake_gaia_.SetFakeMergeSessionParams(kFirstSAMLUserEmail, - kTestAuthSIDCookie1, - kTestAuthLSIDCookie1); + fake_gaia_->SetFakeMergeSessionParams( + kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1); - embedded_test_server()->RegisterRequestHandler( - base::Bind(&FakeGaia::HandleRequest, base::Unretained(&fake_gaia_))); embedded_test_server()->RegisterRequestHandler(base::Bind( &FakeSamlIdp::HandleRequest, base::Unretained(&fake_saml_idp_))); - // Restart the thread as the sandbox host process has already been spawned. - embedded_test_server()->RestartThreadAndListen(); - - login_screen_load_observer_.reset(new content::WindowedNotificationObserver( - chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, - content::NotificationService::AllSources())); - } - - void TearDownOnMainThread() override { - // If the login display is still showing, exit gracefully. - if (LoginDisplayHostImpl::default_host()) { - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(&chrome::AttemptExit)); - content::RunMessageLoop(); - } - } - - WebUILoginDisplay* GetLoginDisplay() { - ExistingUserController* controller = - ExistingUserController::current_controller(); - CHECK(controller); - return static_cast<WebUILoginDisplay*>(controller->login_display()); - } - - void WaitForSigninScreen() { - WizardController* wizard_controller = - WizardController::default_controller(); - if (wizard_controller) { - wizard_controller->SkipToLoginForTesting(LoginScreenContext()); - } - WizardController::SkipPostLoginScreensForTesting(); - - login_screen_load_observer_->Wait(); + OobeBaseTest::SetUpOnMainThread(); } virtual void StartSamlAndWaitForIdpPageLoad(const std::string& gaia_email) { @@ -419,19 +314,6 @@ EXPECT_EQ("\"SamlLoaded\"", message); } - void SetSignFormField(const std::string& field_id, - const std::string& field_value) { - std::string js = - "(function(){" - "document.getElementById('$FieldId').value = '$FieldValue';" - "var e = new Event('input');" - "document.getElementById('$FieldId').dispatchEvent(e);" - "})();"; - ReplaceSubstringsAfterOffset(&js, 0, "$FieldId", field_id); - ReplaceSubstringsAfterOffset(&js, 0, "$FieldValue", field_value); - ExecuteJsInSigninFrame(js); - } - void SendConfirmPassword(const std::string& password_to_confirm) { std::string js = "$('confirm-password-input').value='$Password';" @@ -440,15 +322,6 @@ ASSERT_TRUE(content::ExecuteScript(GetLoginUI()->GetWebContents(), js)); } - void JsExpect(const std::string& js) { - bool result; - EXPECT_TRUE(content::ExecuteScriptAndExtractBool( - GetLoginUI()->GetWebContents(), - "window.domAutomationController.send(!!(" + js + "));", - &result)); - EXPECT_TRUE(result) << js; - } - std::string WaitForAndGetFatalErrorMessage() { OobeScreenWaiter(OobeDisplay::SCREEN_FATAL_ERROR).Wait(); std::string error_message; @@ -462,32 +335,21 @@ return error_message; } - content::WebUI* GetLoginUI() { - return static_cast<LoginDisplayHostImpl*>( - LoginDisplayHostImpl::default_host())->GetOobeUI()->web_ui(); - } - - // Executes JavaScript code in the auth iframe hosted by gaia_auth extension. - void ExecuteJsInSigninFrame(const std::string& js) { - content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe( - GetLoginUI()->GetWebContents(), GURL(), gaia_frame_parent_); - ASSERT_TRUE(content::ExecuteScript(frame, js)); - } - FakeSamlIdp* fake_saml_idp() { return &fake_saml_idp_; } protected: - scoped_ptr<content::WindowedNotificationObserver> login_screen_load_observer_; - FakeGaia fake_gaia_; + void InitHttpsForwarders() override { + saml_https_forwarder_.reset( + new HTTPSForwarder(embedded_test_server()->base_url())); + ASSERT_TRUE(saml_https_forwarder_->Start()); - std::string gaia_frame_parent_; + OobeBaseTest::InitHttpsForwarders(); + } - scoped_ptr<HTTPSForwarder> gaia_https_forwarder_; scoped_ptr<HTTPSForwarder> saml_https_forwarder_; private: FakeSamlIdp fake_saml_idp_; - scoped_ptr<extensions::ScopedCurrentChannel> scoped_channel_; bool saml_load_injected_; @@ -503,13 +365,13 @@ // Saml flow UI expectations. JsExpect("$('gaia-signin').classList.contains('full-width')"); - if (!UseWebView()) { + if (!use_webview_) { JsExpect("!$('cancel-add-user-button').hidden"); } // Click on 'cancel'. content::DOMMessageQueue message_queue; // Observe before 'cancel'. - if (UseWebView()) { + if (use_webview_) { ASSERT_TRUE(content::ExecuteScript( GetLoginUI()->GetWebContents(), "$('close-button-item').click();")); @@ -535,7 +397,7 @@ // webview.executeScript and there is no way to control the injection time. // As a result, this test is flaky and fails about 20% of the time. // TODO(xiyuan): Re-enable when webview.addContentScript API is ready. - if (UseWebView()) + if (use_webview_) return; fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html"); @@ -682,8 +544,8 @@ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); - fake_gaia_.SetFakeMergeSessionParams( - "", kTestAuthSIDCookie1, kTestAuthLSIDCookie1); + fake_gaia_->SetFakeMergeSessionParams("", kTestAuthSIDCookie1, + kTestAuthLSIDCookie1); SetSignFormField("Email", "fake_user"); SetSignFormField("Password", "fake_password"); ExecuteJsInSigninFrame("document.getElementById('Submit').click();"); @@ -823,7 +685,7 @@ token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); token_info.email = kFirstSAMLUserEmail; - fake_gaia_.IssueOAuthToken(kTestRefreshToken, token_info); + fake_gaia_->IssueOAuthToken(kTestRefreshToken, token_info); SamlTest::SetUpOnMainThread(); } @@ -1056,8 +918,8 @@ fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html"); StartSamlAndWaitForIdpPageLoad(user_id); - fake_gaia_.SetFakeMergeSessionParams( - user_id, auth_sid_cookie, auth_lsid_cookie); + fake_gaia_->SetFakeMergeSessionParams(user_id, auth_sid_cookie, + auth_lsid_cookie); SetSignFormField("Email", "fake_user"); SetSignFormField("Password", "fake_password"); ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc index 14819b7..5dcc635 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -5,14 +5,19 @@ #include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "base/command_line.h" +#include "base/json/json_file_value_serializer.h" #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" +#include "chrome/browser/chromeos/login/test/https_forwarder.h" #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/ui/webui/signin/inline_login_ui.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/fake_shill_manager_client.h" #include "components/user_manager/fake_user_manager.h" @@ -30,7 +35,9 @@ OobeBaseTest::OobeBaseTest() : fake_gaia_(new FakeGaia()), network_portal_detector_(NULL), - needs_background_networking_(false) { + needs_background_networking_(false), + gaia_frame_parent_("signin-frame"), + use_webview_(false) { set_exit_when_last_browser_closes(false); set_chromeos_user_ = false; } @@ -42,9 +49,16 @@ base::FilePath test_data_dir; PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); embedded_test_server()->ServeFilesFromDirectory(test_data_dir); + embedded_test_server()->RegisterRequestHandler( base::Bind(&FakeGaia::HandleRequest, base::Unretained(fake_gaia_.get()))); + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + + // Start https wrapper here so that the URLs can be pointed at it in + // SetUpCommandLine(). + InitHttpsForwarders(); + // Stop IO thread here because no threads are allowed while // spawning sandbox host process. See crbug.com/322732. embedded_test_server()->StopThread(); @@ -52,6 +66,35 @@ ExtensionApiTest::SetUp(); } +bool OobeBaseTest::SetUpUserDataDirectory() { + if (use_webview_) { + // Fake Dev channel to enable webview signin. + scoped_channel_.reset( + new extensions::ScopedCurrentChannel(chrome::VersionInfo::CHANNEL_DEV)); + + base::FilePath user_data_dir; + CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); + base::FilePath local_state_path = + user_data_dir.Append(chrome::kLocalStateFilename); + + // Set webview enabled flag only when local state file does not exist. + // Otherwise, we break PRE tests that leave state in it. + if (!base::PathExists(local_state_path)) { + base::DictionaryValue local_state_dict; + local_state_dict.SetBoolean(prefs::kWebviewSigninEnabled, true); + // OobeCompleted to skip controller-pairing-screen which still uses + // iframe and ends up in a JS error in oobe page init. + // See http://crbug.com/467147 + local_state_dict.SetBoolean(prefs::kOobeComplete, true); + + CHECK(JSONFileValueSerializer(local_state_path) + .Serialize(local_state_dict)); + } + } + + return ExtensionApiTest::SetUpUserDataDirectory(); +} + void OobeBaseTest::SetUpInProcessBrowserTestFixture() { host_resolver()->AddRule("*", "127.0.0.1"); network_portal_detector_ = new NetworkPortalDetectorTestImpl(); @@ -66,6 +109,10 @@ // Restart the thread as the sandbox host process has already been spawned. embedded_test_server()->RestartThreadAndListen(); + login_screen_load_observer_.reset(new content::WindowedNotificationObserver( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources())); + ExtensionApiTest::SetUpOnMainThread(); } @@ -82,25 +129,27 @@ void OobeBaseTest::SetUpCommandLine(base::CommandLine* command_line) { ExtensionApiTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(chromeos::switches::kLoginManager); command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests); if (!needs_background_networking_) command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); - // Create gaia and webstore URL from test server url but using different - // host names. This is to avoid gaia response being tagged as from - // webstore in chrome_resource_dispatcher_host_delegate.cc. - const GURL& server_url = embedded_test_server()->base_url(); - - GURL::Replacements replace_gaia_host; - replace_gaia_host.SetHostStr("gaia"); - GURL gaia_url = server_url.ReplaceComponents(replace_gaia_host); + GURL gaia_url = gaia_https_forwarder_->GetURL(""); command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec()); command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec()); command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, gaia_url.spec()); + fake_gaia_->Initialize(); + fake_gaia_->set_issue_oauth_code_cookie(use_webview_); +} + +void OobeBaseTest::InitHttpsForwarders() { + gaia_https_forwarder_.reset( + new HTTPSForwarder(embedded_test_server()->base_url())); + ASSERT_TRUE(gaia_https_forwarder_->Start()); } void OobeBaseTest::SimulateNetworkOffline() { @@ -168,4 +217,33 @@ controller->login_display()); } +void OobeBaseTest::WaitForSigninScreen() { + WizardController* wizard_controller = WizardController::default_controller(); + if (wizard_controller) { + wizard_controller->SkipToLoginForTesting(LoginScreenContext()); + } + WizardController::SkipPostLoginScreensForTesting(); + + login_screen_load_observer_->Wait(); +} + +void OobeBaseTest::ExecuteJsInSigninFrame(const std::string& js) { + content::RenderFrameHost* frame = InlineLoginUI::GetAuthFrame( + GetLoginUI()->GetWebContents(), GURL(), gaia_frame_parent_); + ASSERT_TRUE(content::ExecuteScript(frame, js)); +} + +void OobeBaseTest::SetSignFormField(const std::string& field_id, + const std::string& field_value) { + std::string js = + "(function(){" + "document.getElementById('$FieldId').value = '$FieldValue';" + "var e = new Event('input');" + "document.getElementById('$FieldId').dispatchEvent(e);" + "})();"; + ReplaceSubstringsAfterOffset(&js, 0, "$FieldId", field_id); + ReplaceSubstringsAfterOffset(&js, 0, "$FieldValue", field_value); + ExecuteJsInSigninFrame(js); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h index 0337845..6933a01 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.h +++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -19,13 +19,19 @@ namespace content { class WebUI; +class WindowedNotificationObserver; +} + +namespace extensions { +class ScopedCurrentChannel; } namespace chromeos { +class HTTPSForwarder; class NetworkPortalDetectorTestImpl; -// Base class for OOBE and Kiosk tests. +// Base class for OOBE, login, SAML and Kiosk tests. class OobeBaseTest : public ExtensionApiTest { public: OobeBaseTest(); @@ -35,10 +41,13 @@ // InProcessBrowserTest overrides. void SetUp() override; void SetUpInProcessBrowserTestFixture() override; + bool SetUpUserDataDirectory() override; void SetUpOnMainThread() override; void TearDownOnMainThread() override; void SetUpCommandLine(base::CommandLine* command_line) override; + virtual void InitHttpsForwarders(); + // Network status control functions. void SimulateNetworkOffline(); void SimulateNetworkOnline(); @@ -57,12 +66,25 @@ // Returns login display. WebUILoginDisplay* GetLoginDisplay(); + void WaitForSigninScreen(); + void ExecuteJsInSigninFrame(const std::string& js); + void SetSignFormField(const std::string& field_id, + const std::string& field_value); + scoped_ptr<FakeGaia> fake_gaia_; NetworkPortalDetectorTestImpl* network_portal_detector_; // Whether to use background networking. Note this is only effective when it // is set before SetUpCommandLine is invoked. bool needs_background_networking_; + + scoped_ptr<content::WindowedNotificationObserver> login_screen_load_observer_; + scoped_ptr<extensions::ScopedCurrentChannel> scoped_channel_; + scoped_ptr<HTTPSForwarder> gaia_https_forwarder_; + std::string gaia_frame_parent_; + bool use_webview_; + + DISALLOW_COPY_AND_ASSIGN(OobeBaseTest); }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/login_display.h b/chrome/browser/chromeos/login/ui/login_display.h index d3400b7..d6c70c5 100644 --- a/chrome/browser/chromeos/login/ui/login_display.h +++ b/chrome/browser/chromeos/login/ui/login_display.h
@@ -138,6 +138,10 @@ // Shows signin UI with specified email. virtual void ShowSigninUI(const std::string& email) = 0; + // Show whitelist check failed error. Happens after user completes online + // signin but whitelist check fails. + virtual void ShowWhitelistCheckFailedError() = 0; + gfx::Rect background_bounds() const { return background_bounds_; } void set_background_bounds(const gfx::Rect& background_bounds) { background_bounds_ = background_bounds;
diff --git a/chrome/browser/chromeos/login/ui/mock_login_display.h b/chrome/browser/chromeos/login/ui/mock_login_display.h index f14e741..79f1a88 100644 --- a/chrome/browser/chromeos/login/ui/mock_login_display.h +++ b/chrome/browser/chromeos/login/ui/mock_login_display.h
@@ -26,6 +26,7 @@ MOCK_METHOD1(ShowGaiaPasswordChanged, void(const std::string&)); MOCK_METHOD1(ShowPasswordChangedDialog, void(bool)); MOCK_METHOD1(ShowSigninUI, void(const std::string&)); + MOCK_METHOD0(ShowWhitelistCheckFailedError, void(void)); MOCK_METHOD1(OnBeforeUserRemoved, void(const std::string&)); MOCK_METHOD1(OnUserRemoved, void(const std::string&));
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.cc b/chrome/browser/chromeos/login/ui/webui_login_display.cc index 2c0c417c..cd0817d2 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_display.cc
@@ -195,6 +195,11 @@ webui_handler_->ShowSigninUI(email); } +void WebUILoginDisplay::ShowWhitelistCheckFailedError() { + if (webui_handler_) + webui_handler_->ShowWhitelistCheckFailedError(); +} + // WebUILoginDisplay, NativeWindowDelegate implementation: --------------------- gfx::NativeWindow WebUILoginDisplay::GetNativeWindow() const { return parent_window();
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.h b/chrome/browser/chromeos/login/ui/webui_login_display.h index f71a02e..7005afc 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.h +++ b/chrome/browser/chromeos/login/ui/webui_login_display.h
@@ -44,6 +44,7 @@ void ShowGaiaPasswordChanged(const std::string& username) override; void ShowPasswordChangedDialog(bool show_password_error) override; void ShowSigninUI(const std::string& email) override; + void ShowWhitelistCheckFailedError() override; // NativeWindowDelegate implementation: gfx::NativeWindow GetNativeWindow() const override;
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc new file mode 100644 index 0000000..872d821b --- /dev/null +++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -0,0 +1,78 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" +#include "chrome/browser/chromeos/login/ui/webui_login_display.h" +#include "chromeos/chromeos_switches.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" + +namespace chromeos { +namespace { +const char kFakeUserEmail[] = "fake-email@gmail.com"; +const char kFakeUserPassword[] = "fake-password"; +const char kFakeSIDCookie[] = "fake-SID-cookie"; +const char kFakeLSIDCookie[] = "fake-LSID-cookie"; +} + +class WebviewLoginTest : public OobeBaseTest { + public: + WebviewLoginTest() { use_webview_ = true; } + ~WebviewLoginTest() override {} + + void SetUpOnMainThread() override { + fake_gaia_->SetFakeMergeSessionParams(kFakeUserEmail, kFakeSIDCookie, + kFakeLSIDCookie); + + OobeBaseTest::SetUpOnMainThread(); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kOobeSkipPostLogin); + OobeBaseTest::SetUpCommandLine(command_line); + } + + void WaitForGaiaPageLoaded() { + WaitForSigninScreen(); + + ASSERT_TRUE(content::ExecuteScript( + GetLoginUI()->GetWebContents(), + "$('gaia-signin').gaiaAuthHost_.addEventListener('ready'," + "function() {" + "window.domAutomationController.setAutomationId(0);" + "window.domAutomationController.send('GaiaReady');" + "});")); + + content::DOMMessageQueue message_queue; + std::string message; + ASSERT_TRUE(message_queue.WaitForMessage(&message)); + EXPECT_EQ("\"GaiaReady\"", message); + } + + private: + DISALLOW_COPY_AND_ASSIGN(WebviewLoginTest); +}; + +IN_PROC_BROWSER_TEST_F(WebviewLoginTest, Basic) { + WaitForGaiaPageLoaded(); + + JsExpect("$('close-button-item').hidden"); + + SetSignFormField("identifier", kFakeUserEmail); + ExecuteJsInSigninFrame("document.getElementById('nextButton').click();"); + + JsExpect("$('close-button-item').hidden"); + + content::WindowedNotificationObserver session_start_waiter( + chrome::NOTIFICATION_SESSION_STARTED, + content::NotificationService::AllSources()); + + SetSignFormField("password", kFakeUserPassword); + ExecuteJsInSigninFrame("document.getElementById('nextButton').click();"); + + session_start_waiter.Wait(); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc b/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc new file mode 100644 index 0000000..e6d3faf1 --- /dev/null +++ b/chrome/browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc
@@ -0,0 +1,130 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "ash/display/display_manager.h" +#include "ash/shell.h" +#include "ash/test/display_manager_test_api.h" +#include "ash/wm/window_positioner.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_number_conversions.h" +#include "base/values.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/policy/login_policy_test_base.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/host_desktop.h" +#include "components/user_manager/user.h" +#include "components/user_manager/user_manager.h" +#include "content/public/browser/notification_service.h" +#include "content/public/test/test_utils.h" +#include "policy/policy_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +class ForceMaximizeOnFirstRunTest : public LoginPolicyTestBase { + protected: + ForceMaximizeOnFirstRunTest() : LoginPolicyTestBase() {} + + scoped_ptr<base::DictionaryValue> GetMandatoryPoliciesValue() const override { + scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); + dict->SetBoolean(key::kForceMaximizeOnFirstRun, true); + return dict; + } + + void SetUpResolution() { + // Set a screen resolution for which the first browser window will not be + // maximized by default. + const int width = + ash::WindowPositioner::GetForceMaximizedWidthLimit() + 100; + // Set resolution to 1466x300. + const std::string resolution = base::IntToString(width) + "x300"; + ash::DisplayManager* const display_manager = + ash::Shell::GetInstance()->display_manager(); + ash::test::DisplayManagerTestApi display_manager_test_api(display_manager); + display_manager_test_api.UpdateDisplay(resolution); + } + + const Browser* OpenNewBrowserWindow() { + const user_manager::User* const user = + user_manager::UserManager::Get()->GetActiveUser(); + Profile* const profile = + chromeos::ProfileHelper::Get()->GetProfileByUser(user); + return CreateBrowser(profile); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ForceMaximizeOnFirstRunTest); +}; + +IN_PROC_BROWSER_TEST_F(ForceMaximizeOnFirstRunTest, PRE_TwoRuns) { + SetUpResolution(); + SkipToLoginScreen(); + LogIn(kAccountId, kAccountPassword); + + // Check that the first browser window is maximized. + const BrowserList* const browser_list = + BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); + EXPECT_EQ(1U, browser_list->size()); + const Browser* const browser = browser_list->get(0); + ASSERT_TRUE(browser); + EXPECT_TRUE(browser->window()->IsMaximized()); + + // Un-maximize the window as its state will be carried forward to the next + // opened window. + browser->window()->Restore(); + EXPECT_FALSE(browser->window()->IsMaximized()); + + // Create a second window and check that it is not affected by the policy. + const Browser* const browser1 = OpenNewBrowserWindow(); + ASSERT_TRUE(browser1); + EXPECT_FALSE(browser1->window()->IsMaximized()); +} + +IN_PROC_BROWSER_TEST_F(ForceMaximizeOnFirstRunTest, TwoRuns) { + SetUpResolution(); + content::WindowedNotificationObserver( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()).Wait(); + LogIn(kAccountId, kAccountPassword); + + const Browser* const browser = OpenNewBrowserWindow(); + ASSERT_TRUE(browser); + EXPECT_FALSE(browser->window()->IsMaximized()); +} + +class ForceMaximizetPolicyFalseTest : public ForceMaximizeOnFirstRunTest { + protected: + ForceMaximizetPolicyFalseTest() : ForceMaximizeOnFirstRunTest() {} + + scoped_ptr<base::DictionaryValue> GetMandatoryPoliciesValue() const override { + scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); + dict->SetBoolean(key::kForceMaximizeOnFirstRun, false); + return dict; + } + + private: + DISALLOW_COPY_AND_ASSIGN(ForceMaximizetPolicyFalseTest); +}; + +IN_PROC_BROWSER_TEST_F(ForceMaximizetPolicyFalseTest, GeneralFirstRun) { + SetUpResolution(); + SkipToLoginScreen(); + LogIn(kAccountId, kAccountPassword); + + const BrowserList* const browser_list = + BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); + EXPECT_EQ(1U, browser_list->size()); + const Browser* const browser = browser_list->get(0); + ASSERT_TRUE(browser); + EXPECT_FALSE(browser->window()->IsMaximized()); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.cc b/chrome/browser/chromeos/policy/login_policy_test_base.cc new file mode 100644 index 0000000..5525ccf --- /dev/null +++ b/chrome/browser/chromeos/policy/login_policy_test_base.cc
@@ -0,0 +1,166 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/json/json_writer.h" +#include "base/values.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/ui/webui_login_display.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/login_policy_test_base.h" +#include "chrome/browser/policy/test/local_policy_test_server.h" +#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/policy_switches.h" +#include "content/public/browser/notification_service.h" +#include "content/public/test/test_utils.h" +#include "google_apis/gaia/fake_gaia.h" +#include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/gaia_urls.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace policy { + +namespace { + +const char kTestAuthCode[] = "fake-auth-code"; +const char kTestGaiaUberToken[] = "fake-uber-token"; +const char kTestAuthLoginAccessToken[] = "fake-access-token"; +const char kTestRefreshToken[] = "fake-refresh-token"; +const char kTestAuthSIDCookie[] = "fake-auth-SID-cookie"; +const char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie"; +const char kTestSessionSIDCookie[] = "fake-session-SID-cookie"; +const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie"; +const char kTestUserinfoToken[] = "fake-userinfo-token"; + +std::string GetPolicy(scoped_ptr<base::DictionaryValue> mandatory, + scoped_ptr<base::DictionaryValue> recommended, + const std::string& policyType, + const std::string& account) { + scoped_ptr<base::DictionaryValue> policy_type_dict(new base::DictionaryValue); + policy_type_dict->Set("mandatory", mandatory.Pass()); + policy_type_dict->Set("recommended", recommended.Pass()); + + scoped_ptr<base::ListValue> managed_users_list(new base::ListValue); + managed_users_list->AppendString("*"); + + base::DictionaryValue root_dict; + root_dict.Set(policyType, policy_type_dict.Pass()); + root_dict.Set("managed_users", managed_users_list.Pass()); + root_dict.SetString("policy_user", account); + root_dict.SetInteger("current_key_index", 0); + + std::string jsonPolicy; + base::JSONWriter::WriteWithOptions( + &root_dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &jsonPolicy); + return jsonPolicy; +} + +} // namespace + +const char LoginPolicyTestBase::kAccountPassword[] = "letmein"; +const char LoginPolicyTestBase::kAccountId[] = "user@example.com"; + +LoginPolicyTestBase::LoginPolicyTestBase() { + set_open_about_blank_on_browser_launch(false); +} + +LoginPolicyTestBase::~LoginPolicyTestBase() { +} + +void LoginPolicyTestBase::SetUp() { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + SetServerPolicy(); + + test_server_.reset(new LocalPolicyTestServer(PolicyFilePath())); + ASSERT_TRUE(test_server_->Start()); + + OobeBaseTest::SetUp(); +} + +void LoginPolicyTestBase::SetUpCommandLine(base::CommandLine* command_line) { + command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl, + test_server_->GetServiceURL().spec()); + OobeBaseTest::SetUpCommandLine(command_line); +} + +void LoginPolicyTestBase::SetUpOnMainThread() { + SetMergeSessionParams(kAccountId); + SetUpGaiaServerWithAccessTokens(); + OobeBaseTest::SetUpOnMainThread(); +} + +scoped_ptr<base::DictionaryValue> +LoginPolicyTestBase::GetMandatoryPoliciesValue() const { + return make_scoped_ptr(new base::DictionaryValue); +} + +scoped_ptr<base::DictionaryValue> +LoginPolicyTestBase::GetRecommendedPoliciesValue() const { + return make_scoped_ptr(new base::DictionaryValue); +} + +void LoginPolicyTestBase::SetUpGaiaServerWithAccessTokens() { + FakeGaia::AccessTokenInfo token_info; + token_info.token = kTestUserinfoToken; + token_info.scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); + token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); + token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); + token_info.email = kAccountId; + fake_gaia_->IssueOAuthToken(kTestRefreshToken, token_info); +} + +void LoginPolicyTestBase::SetMergeSessionParams(const std::string& email) { + FakeGaia::MergeSessionParams params; + params.auth_sid_cookie = kTestAuthSIDCookie; + params.auth_lsid_cookie = kTestAuthLSIDCookie; + params.auth_code = kTestAuthCode; + params.refresh_token = kTestRefreshToken; + params.access_token = kTestAuthLoginAccessToken; + params.gaia_uber_token = kTestGaiaUberToken; + params.session_sid_cookie = kTestSessionSIDCookie; + params.session_lsid_cookie = kTestSessionLSIDCookie; + params.email = email; + fake_gaia_->SetMergeSessionParams(params); +} + +void LoginPolicyTestBase::SkipToLoginScreen() { + chromeos::WizardController::SkipPostLoginScreensForTesting(); + chromeos::WizardController* const wizard_controller = + chromeos::WizardController::default_controller(); + ASSERT_TRUE(wizard_controller); + wizard_controller->SkipToLoginForTesting(chromeos::LoginScreenContext()); + + content::WindowedNotificationObserver( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()).Wait(); +} + +void LoginPolicyTestBase::LogIn(const std::string& user_id, + const std::string& password) { + GetLoginDisplay()->ShowSigninScreenForCreds(user_id, password); + + content::WindowedNotificationObserver( + chrome::NOTIFICATION_SESSION_STARTED, + content::NotificationService::AllSources()).Wait(); +} + +void LoginPolicyTestBase::SetServerPolicy() { + const std::string policy = + GetPolicy(GetMandatoryPoliciesValue(), GetRecommendedPoliciesValue(), + dm_protocol::kChromeUserPolicyType, kAccountId); + + const int bytes_written = + base::WriteFile(PolicyFilePath(), policy.data(), policy.size()); + ASSERT_EQ(static_cast<int>(policy.size()), bytes_written); +} + +base::FilePath LoginPolicyTestBase::PolicyFilePath() const { + return temp_dir_.path().AppendASCII("policy.json"); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.h b/chrome/browser/chromeos/policy/login_policy_test_base.h new file mode 100644 index 0000000..cf4f8480 --- /dev/null +++ b/chrome/browser/chromeos/policy/login_policy_test_base.h
@@ -0,0 +1,59 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_POLICY_TEST_BASE_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_POLICY_TEST_BASE_H_ + +#include <string> + +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" + +namespace base { +class FilePath; +class DictionaryValue; +} + +namespace policy { + +class LocalPolicyTestServer; + +// This class can be used to implement tests which need policy to be set prior +// to login. +class LoginPolicyTestBase : public chromeos::OobeBaseTest { + protected: + LoginPolicyTestBase(); + ~LoginPolicyTestBase() override; + + // chromeos::OobeBaseTest:: + void SetUp() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpOnMainThread() override; + + virtual scoped_ptr<base::DictionaryValue> GetMandatoryPoliciesValue() const; + virtual scoped_ptr<base::DictionaryValue> GetRecommendedPoliciesValue() const; + + void SkipToLoginScreen(); + void LogIn(const std::string& user_id, const std::string& password); + + static const char kAccountPassword[]; + static const char kAccountId[]; + + private: + void SetUpGaiaServerWithAccessTokens(); + void SetMergeSessionParams(const std::string& email); + void SetServerPolicy(); + base::FilePath PolicyFilePath() const; + + scoped_ptr<LocalPolicyTestServer> test_server_; + base::ScopedTempDir temp_dir_; + + DISALLOW_COPY_AND_ASSIGN(LoginPolicyTestBase); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_POLICY_TEST_BASE_H_
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc index 4eaaf82..fff0036 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc
@@ -4,167 +4,44 @@ #include <string> -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "base/strings/stringprintf.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/login/test/oobe_base_test.h" -#include "chrome/browser/chromeos/login/wizard_controller.h" -#include "chrome/browser/policy/test/local_policy_test_server.h" +#include "base/values.h" +#include "chrome/browser/chromeos/policy/login_policy_test_base.h" +#include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/host_desktop.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" -#include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/policy/core/common/policy_switches.h" -#include "content/public/browser/notification_service.h" -#include "content/public/test/test_utils.h" -#include "google_apis/gaia/fake_gaia.h" -#include "google_apis/gaia/gaia_constants.h" -#include "google_apis/gaia/gaia_urls.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" +#include "policy/policy_constants.h" namespace policy { -namespace { - -const char kAccountId[] = "dla1@example.com"; -const char kAccountPassword[] = "letmein"; -const char* const kStartupURLs[] = {"chrome://policy", "chrome://about"}; -const char kTestAuthCode[] = "fake-auth-code"; -const char kTestGaiaUberToken[] = "fake-uber-token"; -const char kTestAuthLoginAccessToken[] = "fake-access-token"; -const char kTestRefreshToken[] = "fake-refresh-token"; -const char kTestAuthSIDCookie[] = "fake-auth-SID-cookie"; -const char kTestAuthLSIDCookie[] = "fake-auth-LSID-cookie"; -const char kTestSessionSIDCookie[] = "fake-session-SID-cookie"; -const char kTestSessionLSIDCookie[] = "fake-session-LSID-cookie"; -const char kTestUserinfoToken[] = "fake-userinfo-token"; - -} // namespace - -class UserCloudPolicyManagerTest : public chromeos::OobeBaseTest { +class UserCloudPolicyManagerTest : public LoginPolicyTestBase { protected: - UserCloudPolicyManagerTest() { - set_open_about_blank_on_browser_launch(false); + UserCloudPolicyManagerTest() : LoginPolicyTestBase() {} + + scoped_ptr<base::DictionaryValue> GetMandatoryPoliciesValue() const override { + scoped_ptr<base::ListValue> list(new base::ListValue); + list->AppendString("chrome://policy"); + list->AppendString("chrome://about"); + + scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); + dict->Set(key::kRestoreOnStartupURLs, list.Pass()); + dict->SetInteger(key::kRestoreOnStartup, + SessionStartupPref::kPrefValueURLs); + + return dict; } - ~UserCloudPolicyManagerTest() override {} - - void SetUp() override { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - SetServerPolicy(); - - test_server_.reset(new LocalPolicyTestServer(policy_file_path())); - ASSERT_TRUE(test_server_->Start()); - - OobeBaseTest::SetUp(); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl, - test_server_->GetServiceURL().spec()); - OobeBaseTest::SetUpCommandLine(command_line); - } - - void SetUpOnMainThread() override { - SetMergeSessionParams(kAccountId); - SetupGaiaServerWithAccessTokens(); - OobeBaseTest::SetUpOnMainThread(); - } - - void SetupGaiaServerWithAccessTokens() { - FakeGaia::AccessTokenInfo token_info; - token_info.token = kTestUserinfoToken; - token_info.scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); - token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); - token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); - token_info.email = kAccountId; - fake_gaia_->IssueOAuthToken(kTestRefreshToken, token_info); - } - - void SetMergeSessionParams(const std::string& email) { - FakeGaia::MergeSessionParams params; - params.auth_sid_cookie = kTestAuthSIDCookie; - params.auth_lsid_cookie = kTestAuthLSIDCookie; - params.auth_code = kTestAuthCode; - params.refresh_token = kTestRefreshToken; - params.access_token = kTestAuthLoginAccessToken; - params.gaia_uber_token = kTestGaiaUberToken; - params.session_sid_cookie = kTestSessionSIDCookie; - params.session_lsid_cookie = kTestSessionLSIDCookie; - params.email = email; - fake_gaia_->SetMergeSessionParams(params); - } - - void SkipToLoginScreen() { - chromeos::WizardController::SkipPostLoginScreensForTesting(); - chromeos::WizardController* wizard_controller = - chromeos::WizardController::default_controller(); - ASSERT_TRUE(wizard_controller); - wizard_controller->SkipToLoginForTesting(chromeos::LoginScreenContext()); - - content::WindowedNotificationObserver( - chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, - content::NotificationService::AllSources()).Wait(); - } - - void LogIn(const std::string& user_id, const std::string& password) { - GetLoginDisplay()->ShowSigninScreenForCreds(user_id, password); - - content::WindowedNotificationObserver( - chrome::NOTIFICATION_SESSION_STARTED, - content::NotificationService::AllSources()).Wait(); - } - - void SetServerPolicy() { - const char kPolicy[] = - "{" - " \"%s\": {" - " \"mandatory\": {" - " \"RestoreOnStartup\": 4," - " \"RestoreOnStartupURLs\": [" - " \"chrome://policy\"," - " \"chrome://about\"" - " ]" - " }," - " \"recommended\": {}" - " }," - " \"managed_users\": [ \"*\" ]," - " \"policy_user\": \"%s\"," - " \"current_key_index\": 0" - "}"; - - const std::string policy = base::StringPrintf( - kPolicy, dm_protocol::kChromeUserPolicyType, kAccountId); - - const int bytes_written = - base::WriteFile(policy_file_path(), policy.data(), policy.size()); - ASSERT_EQ(static_cast<int>(policy.size()), bytes_written); - } - - base::FilePath policy_file_path() const { - return temp_dir_.path().AppendASCII("policy.json"); - } - - scoped_ptr<LocalPolicyTestServer> test_server_; - - base::ScopedTempDir temp_dir_; - private: DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyManagerTest); }; IN_PROC_BROWSER_TEST_F(UserCloudPolicyManagerTest, StartSession) { - SkipToLoginScreen(); + const char* const kStartupURLs[] = {"chrome://policy", "chrome://about"}; + SkipToLoginScreen(); LogIn(kAccountId, kAccountPassword); // Check that the startup pages specified in policy were opened.
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index e0cb1f5..ba4f242fba 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -333,6 +333,10 @@ registry->RegisterBooleanPref( prefs::kCaptivePortalAuthenticationIgnoresProxy, true, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + + registry->RegisterBooleanPref( + prefs::kForceMaximizeOnFirstRun, false, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); } void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) {
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc index 5505565..b39b6c5 100644 --- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc +++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
@@ -191,6 +191,8 @@ d->RegisterHandler("sendMessageToBrowser", &Delegate::SendMessageToBrowser, delegate); d->RegisterHandler("recordActionUMA", &Delegate::RecordActionUMA, delegate); + d->RegisterHandler("recordEnumeratedHistogram", + &Delegate::RecordEnumeratedHistogram, delegate); d->RegisterHandlerWithCallback("sendJsonRequest", &Delegate::SendJsonRequest, delegate); return d;
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h index 665040c2..5d72ede4 100644 --- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h +++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
@@ -68,6 +68,9 @@ virtual void SetDevicesUpdatesEnabled(bool enabled) = 0; virtual void SendMessageToBrowser(const std::string& message) = 0; virtual void RecordActionUMA(const std::string& name, int action) = 0; + virtual void RecordEnumeratedHistogram(const std::string& name, + int sample, + int boundary_value) = 0; virtual void SendJsonRequest(const DispatchCallback& callback, const std::string& browser_id, const std::string& url) = 0;
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 03c3c97..50f8b04 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -749,6 +749,24 @@ UMA_HISTOGRAM_ENUMERATION(name, action, kDevToolsPanelShownBoundary); } +void DevToolsUIBindings::RecordEnumeratedHistogram(const std::string& name, + int sample, + int boundary_value) { + if (!(boundary_value >= 0 && boundary_value < 100 && sample >= 0 && + sample < boundary_value)) { + frontend_host_->BadMessageRecieved(); + return; + } + // Each histogram name must follow a different code path in + // order to UMA_HISTOGRAM_ENUMERATION work correctly. + if (name == kDevToolsActionTakenHistogram) + UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value); + else if (name == kDevToolsPanelShownHistogram) + UMA_HISTOGRAM_ENUMERATION(name, sample, boundary_value); + else + frontend_host_->BadMessageRecieved(); +} + void DevToolsUIBindings::SendJsonRequest(const DispatchCallback& callback, const std::string& browser_id, const std::string& url) {
diff --git a/chrome/browser/devtools/devtools_ui_bindings.h b/chrome/browser/devtools/devtools_ui_bindings.h index dd238c7..b1ff6e3c 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.h +++ b/chrome/browser/devtools/devtools_ui_bindings.h
@@ -133,6 +133,9 @@ void SetDevicesUpdatesEnabled(bool enabled) override; void SendMessageToBrowser(const std::string& message) override; void RecordActionUMA(const std::string& name, int action) override; + void RecordEnumeratedHistogram(const std::string& name, + int sample, + int boundary_value) override; void SendJsonRequest(const DispatchCallback& callback, const std::string& browser_id, const std::string& url) override;
diff --git a/chrome/browser/diagnostics/sqlite_diagnostics.cc b/chrome/browser/diagnostics/sqlite_diagnostics.cc index b2746227..b342bba1 100644 --- a/chrome/browser/diagnostics/sqlite_diagnostics.cc +++ b/chrome/browser/diagnostics/sqlite_diagnostics.cc
@@ -56,7 +56,7 @@ case DIAG_SQLITE_DB_CORRUPTED: LOG(WARNING) << "Removing broken SQLite database: " << db_path_.value(); - base::DeleteFile(db_path_, false); + sql::Connection::Delete(db_path_); break; case DIAG_SQLITE_SUCCESS: case DIAG_SQLITE_FILE_NOT_FOUND_OK:
diff --git a/chrome/browser/download/download_permission_request.cc b/chrome/browser/download/download_permission_request.cc index 223165f..891664c 100644 --- a/chrome/browser/download/download_permission_request.cc +++ b/chrome/browser/download/download_permission_request.cc
@@ -11,7 +11,11 @@ DownloadPermissionRequest::DownloadPermissionRequest( base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host) - : host_(host) {} + : host_(host) { + const content::WebContents* web_contents = host_->web_contents(); + DCHECK(web_contents); + request_url_ = web_contents->GetURL(); +} DownloadPermissionRequest::~DownloadPermissionRequest() {} @@ -37,11 +41,7 @@ } GURL DownloadPermissionRequest::GetRequestingHostname() const { - const content::WebContents* web_contents = host_->web_contents(); - if (web_contents) { - return web_contents->GetURL(); - } - return GURL(); + return request_url_; } void DownloadPermissionRequest::PermissionGranted() {
diff --git a/chrome/browser/download/download_permission_request.h b/chrome/browser/download/download_permission_request.h index b067d4d..14c3afe7a 100644 --- a/chrome/browser/download/download_permission_request.h +++ b/chrome/browser/download/download_permission_request.h
@@ -33,6 +33,7 @@ private: base::WeakPtr<DownloadRequestLimiter::TabDownloadState> host_; + GURL request_url_; DISALLOW_COPY_AND_ASSIGN(DownloadPermissionRequest); };
diff --git a/chrome/browser/extensions/activity_log/activity_database_unittest.cc b/chrome/browser/extensions/activity_log/activity_database_unittest.cc index 3944384..7d49898 100644 --- a/chrome/browser/extensions/activity_log/activity_database_unittest.cc +++ b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
@@ -174,7 +174,7 @@ base::FilePath db_file; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); db_file = temp_dir.path().AppendASCII("ActivityInit.db"); - base::DeleteFile(db_file, false); + sql::Connection::Delete(db_file); ActivityDatabase* activity_db = OpenDatabase(db_file); activity_db->Close(); @@ -191,7 +191,7 @@ base::FilePath db_file; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); db_file = temp_dir.path().AppendASCII("ActivityRecord.db"); - base::DeleteFile(db_file, false); + sql::Connection::Delete(db_file); ActivityDatabase* activity_db = OpenDatabase(db_file); activity_db->SetBatchModeForTesting(false); @@ -210,7 +210,7 @@ base::FilePath db_file; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); db_file = temp_dir.path().AppendASCII("ActivityRecord.db"); - base::DeleteFile(db_file, false); + sql::Connection::Delete(db_file); // Record some actions ActivityDatabase* activity_db = OpenDatabase(db_file); @@ -228,7 +228,7 @@ base::FilePath db_file; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); db_file = temp_dir.path().AppendASCII("ActivityRecord.db"); - base::DeleteFile(db_file, false); + sql::Connection::Delete(db_file); // Record some actions ActivityDatabase* activity_db = OpenDatabase(db_file); @@ -250,7 +250,7 @@ base::FilePath db_file; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); db_file = temp_dir.path().AppendASCII("ActivityFlush.db"); - base::DeleteFile(db_file, false); + sql::Connection::Delete(db_file); // Record some actions ActivityDatabase* activity_db = OpenDatabase(db_file); @@ -272,7 +272,7 @@ base::FilePath db_file; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); db_file = temp_dir.path().AppendASCII("ActivityRecord.db"); - base::DeleteFile(db_file, false); + sql::Connection::Delete(db_file); ActivityDatabaseTestPolicy* delegate = new ActivityDatabaseTestPolicy(); ActivityDatabase* activity_db = new ActivityDatabase(delegate);
diff --git a/chrome/browser/extensions/api/mdns/mdns_api.cc b/chrome/browser/extensions/api/mdns/mdns_api.cc index 2a7c41d2..1dfa4ff 100644 --- a/chrome/browser/extensions/api/mdns/mdns_api.cc +++ b/chrome/browser/extensions/api/mdns/mdns_api.cc
@@ -9,7 +9,11 @@ #include "base/lazy_instance.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/common/extensions/api/mdns.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "extensions/browser/extension_host.h" #include "extensions/browser/extension_registry.h" +#include "extensions/common/extension_messages.h" namespace extensions { @@ -84,35 +88,10 @@ void MDnsAPI::UpdateMDnsListeners(const EventListenerInfo& details) { std::set<std::string> new_service_types; - - // Check all listeners for service type filters. - const EventListenerMap::ListenerList& listeners = - extensions::EventRouter::Get(browser_context_) - ->listeners() - .GetEventListenersByName(details.event_name); - for (EventListenerMap::ListenerList::const_iterator it = listeners.begin(); - it != listeners.end(); ++it) { - base::DictionaryValue* filter = ((*it)->filter()); - - std::string filter_value; - filter->GetStringASCII(kEventFilterServiceTypeKey, &filter_value); - if (filter_value.empty()) - continue; - - const Extension* extension = ExtensionRegistry::Get(browser_context_)-> - enabled_extensions().GetByID((*it)->extension_id()); - // Don't listen for services associated only with disabled extensions. - if (!extension) - continue; - - // Platform apps may query for all services; other types of extensions are - // restricted to a whitelist. - if (!extension->is_platform_app() && - !IsServiceTypeWhitelisted(filter_value)) - continue; - - new_service_types.insert(filter_value); - } + GetValidOnServiceListListeners( + "" /* service_type_filter - blank = all services */, + nullptr /* extension_ids */, + &new_service_types); // Find all the added and removed service types since last update. std::set<std::string> added_service_types = @@ -140,6 +119,22 @@ std::vector<linked_ptr<mdns::MDnsService> > args; for (DnsSdRegistry::DnsSdServiceList::const_iterator it = services.begin(); it != services.end(); ++it) { + if (static_cast<long>(args.size()) == + api::mdns::MAX_SERVICE_INSTANCES_PER_EVENT) { + // TODO(reddaly): This is not the most meaningful way of notifying the + // application that something bad happened. It will go to the user's + // console (which most users don't look at)and the developer will be none + // the wiser. Instead, changing the event to pass the number of + // discovered instances would allow the caller to know when the list is + // truncated and tell the user something meaningful in the extension/app. + WriteToConsole(service_type, + content::CONSOLE_MESSAGE_LEVEL_WARNING, + base::StringPrintf( + "Truncating number of service instances in " + "onServiceList to maximum allowed: %d", + api::mdns::MAX_SERVICE_INSTANCES_PER_EVENT)); + break; + } linked_ptr<mdns::MDnsService> mdns_service = make_linked_ptr(new mdns::MDnsService); mdns_service->service_name = (*it).service_name; @@ -162,4 +157,70 @@ extensions::EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass()); } +void MDnsAPI::GetValidOnServiceListListeners( + const std::string& service_type_filter, + std::set<std::string>* extension_ids, + std::set<std::string>* service_types) { + for (const auto& listener : + extensions::EventRouter::Get(browser_context_)->listeners() + .GetEventListenersByName(mdns::OnServiceList::kEventName)) { + base::DictionaryValue* filter = listener->filter(); + + std::string service_type; + filter->GetStringASCII(kEventFilterServiceTypeKey, &service_type); + if (service_type.empty()) + continue; + + // Match service type when filter isn't "" + if (!service_type_filter.empty() && service_type_filter != service_type) + continue; + + const Extension* extension = ExtensionRegistry::Get(browser_context_)-> + enabled_extensions().GetByID(listener->extension_id()); + // Don't listen for services associated only with disabled extensions. + if (!extension) + continue; + + // Platform apps may query for all services; other types of extensions are + // restricted to a whitelist. + if (!extension->is_platform_app() && + !IsServiceTypeWhitelisted(service_type)) + continue; + + if (extension_ids) + extension_ids->insert(listener->extension_id()); + if (service_types) + service_types->insert(service_type); + } +} + +void MDnsAPI::WriteToConsole(const std::string& service_type, + content::ConsoleMessageLevel level, + const std::string& message) { + // Get all the extensions with an onServiceList listener for a particular + // service type. + std::set<std::string> extension_ids; + GetValidOnServiceListListeners(service_type, + &extension_ids, + nullptr /* service_types */); + + std::string logged_message(std::string("[chrome.mdns] ") + message); + + // Log to the consoles of the background pages for those extensions. + for (const std::string& extension_id : extension_ids) { + extensions::ExtensionHost* host = + extensions::ProcessManager::Get(browser_context_) + ->GetBackgroundHostForExtension(extension_id); + if (!host) + continue; + content::RenderViewHost* rvh = host->render_view_host(); + if (!rvh) + continue; + rvh->Send(new ExtensionMsg_AddMessageToConsole( + rvh->GetRoutingID(), + level, + logged_message)); + } +} + } // namespace extensions
diff --git a/chrome/browser/extensions/api/mdns/mdns_api.h b/chrome/browser/extensions/api/mdns/mdns_api.h index f232d3b0..95e8428 100644 --- a/chrome/browser/extensions/api/mdns/mdns_api.h +++ b/chrome/browser/extensions/api/mdns/mdns_api.h
@@ -13,6 +13,7 @@ #include "chrome/browser/extensions/api/mdns/dns_sd_registry.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" +#include "extensions/browser/extension_function.h" namespace content { class BrowserContext; @@ -67,6 +68,20 @@ // Update the current list of service types and update the registry. void UpdateMDnsListeners(const EventListenerInfo& details); + // Write a message to the consoles of extensions listening to a given service + // type. + void WriteToConsole(const std::string& service_type, + content::ConsoleMessageLevel level, + const std::string& message); + + // Finds all all the valid listeners of the mdns.onServiceList event and + // filters them by service type if |service_type_filter| is non-empty. The + // extension ids and matched service types are output to |extension_ids| and + // |service_types|, respectively, if the supplied pointers is non-null. + void GetValidOnServiceListListeners(const std::string& service_type_filter, + std::set<std::string>* extension_ids, + std::set<std::string>* service_types); + // Ensure methods are only called on UI thread. base::ThreadChecker thread_checker_; content::BrowserContext* const browser_context_;
diff --git a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc index ede2a2b5..86c0c86 100644 --- a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc +++ b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
@@ -63,10 +63,7 @@ MDnsAPITestingFactoryFunction); // Create an event router and associate it with the context. - extensions::EventRouter* event_router = new extensions::EventRouter( - browser_context(), - ExtensionPrefsFactory::GetInstance()->GetForBrowserContext( - browser_context())); + extensions::EventRouter* event_router = CreateEventRouter_(); static_cast<TestExtensionSystem*>( ExtensionSystem::Get(browser_context()))->SetEventRouter( scoped_ptr<extensions::EventRouter>(event_router)); @@ -133,6 +130,14 @@ return render_process_host_.get(); } + protected: + virtual extensions::EventRouter* CreateEventRouter_() { + return new extensions::EventRouter( + browser_context(), + ExtensionPrefsFactory::GetInstance()->GetForBrowserContext( + browser_context())); + } + private: // The registry is owned by MDnsAPI, but MDnsAPI does not have an accessor // for it, so use a private member. @@ -212,6 +217,103 @@ filter, false); } +class MockEventRouter : public EventRouter { + public: + explicit MockEventRouter(content::BrowserContext* browser_context, + ExtensionPrefs* extension_prefs) : + EventRouter(browser_context, extension_prefs) {} + virtual ~MockEventRouter() {} + + virtual void BroadcastEvent(scoped_ptr<Event> event) { + BroadcastEventPtr(event.get()); + } + MOCK_METHOD1(BroadcastEventPtr, void(Event* event)); +}; + +class MDnsAPIMaxServicesTest : public MDnsAPITest { + public: + MockEventRouter* event_router() { + return static_cast<MockEventRouter*>(EventRouter::Get(browser_context())); + } + protected: + extensions::EventRouter* CreateEventRouter_() override { + return new MockEventRouter( + browser_context(), + ExtensionPrefsFactory::GetInstance()->GetForBrowserContext( + browser_context())); + } +}; + +class EventServiceListSizeMatcher : + public testing::MatcherInterface<const Event&> { + public: + explicit EventServiceListSizeMatcher(size_t expected_size) + : expected_size_(expected_size) {} + + virtual bool MatchAndExplain(const Event& e, + testing::MatchResultListener* listener) const { + if (e.event_args.get() == nullptr) { + *listener << "event.event_arg is null when it shouldn't be"; + return false; + } + if (e.event_args->GetSize() != 1) { + *listener << "event.event_arg.GetSize() should be 1 but is " + << e.event_args->GetSize(); + return false; + } + const base::ListValue* services = nullptr; + { + const base::Value* out; + e.event_args->Get(0, &out); + services = static_cast<const base::ListValue*>(out); + } + if (services == nullptr) { + *listener << "event's service list argument is not a ListValue"; + return false; + } + *listener << "number of services is " + << services->GetSize(); + return static_cast<testing::Matcher<size_t>>(testing::Eq(expected_size_)) + .MatchAndExplain(services->GetSize(), listener); + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "is an onServiceList event where the number of services is " + << expected_size_; + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "isn't an onServiceList event where the number of services is " + << expected_size_; + } + private: + size_t expected_size_; +}; + +inline testing::Matcher<const Event&> EventServiceListSize( + size_t expected_size) { + return testing::MakeMatcher(new EventServiceListSizeMatcher(expected_size)); +} + +TEST_F(MDnsAPIMaxServicesTest, OnServiceListDoesNotExceedLimit) { + // This check should change when the [value=64] changes in the IDL file. + EXPECT_EQ(64, api::mdns::MAX_SERVICE_INSTANCES_PER_EVENT); + + // Dispatch an mDNS event with more service instances than the max, and ensure + // that the list is truncated by inspecting the argument to MockEventRouter's + // BroadcastEvent method. + DnsSdRegistry::DnsSdServiceList services; + for (int i=0; i < api::mdns::MAX_SERVICE_INSTANCES_PER_EVENT + 10; ++i) { + services.push_back(DnsSdService()); + } + EXPECT_CALL( + *event_router(), + BroadcastEventPtr( + testing::Pointee(EventServiceListSize(size_t(64))))) + .Times(1); + dns_sd_registry()->DispatchMDnsEvent("_testing._tcp.local", services); +} + } // empty namespace } // namespace extensions
diff --git a/chrome/browser/extensions/api/mdns/mdns_apitest.cc b/chrome/browser/extensions/api/mdns/mdns_apitest.cc index 80f6e8b..f7b87be9 100644 --- a/chrome/browser/extensions/api/mdns/mdns_apitest.cc +++ b/chrome/browser/extensions/api/mdns/mdns_apitest.cc
@@ -165,3 +165,17 @@ EXPECT_TRUE(RunPlatformAppTest("mdns/api-packaged-apps")) << message_; } + +// TODO(justinlin): Win Dbg has a workaround that makes RunExtensionSubtest +// always return true without actually running the test. Remove when fixed. +#if defined(OS_WIN) && !defined(NDEBUG) +#define MAYBE_MaxServiceInstancesPerEventConst \ + DISABLED_MaxServiceInstancesPerEventConst +#else +#define MAYBE_MaxServiceInstancesPerEventConst MaxServiceInstancesPerEventConst +#endif +// Test loading extension and registering multiple listeners. +IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_MaxServiceInstancesPerEventConst) { + EXPECT_TRUE(RunExtensionSubtest("mdns/api", + "get_max_service_instances.html")); +}
diff --git a/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc b/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc index e729c65..01944907 100644 --- a/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc +++ b/chrome/browser/extensions/api/music_manager_private/music_manager_private_browsertest.cc
@@ -12,17 +12,8 @@ }; IN_PROC_BROWSER_TEST_F(MusicManagerPrivateTest, DeviceIdValueReturned) { -#if defined(OS_MACOSX) || defined(OS_LINUX) - // Note: Some MacOS/Linux trybots seem to run under VMware, which assigns - // MAC addresses that are blacklisted. We still want the test - // to succeed in that case. - const char* custom_arg = "device_id_may_be_undefined"; -#else - const char* custom_arg = NULL; -#endif - ASSERT_TRUE(RunPlatformAppTestWithArg( - "platform_apps/music_manager_private/device_id_value_returned", - custom_arg)) + ASSERT_TRUE(RunPlatformAppTest( + "platform_apps/music_manager_private/device_id_value_returned")) << message_; }
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc index c3b720e..a86e94eb 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
@@ -187,7 +187,7 @@ // Ideally we'd like to run a higher capture rate when vsync is disabled, // but libjingle currently doesn't allow that. // page += HasFlag(kDisableVsync) ? "&fps=300" : "&fps=30"; - page += "&fps=30"; + page += "&fps=60"; ASSERT_TRUE(RunExtensionSubtest("tab_capture", page)) << message_; ASSERT_TRUE(tracing::EndTracing(&json_events)); scoped_ptr<trace_analyzer::TraceAnalyzer> analyzer;
diff --git a/chrome/browser/extensions/permission_message_combinations_unittest.cc b/chrome/browser/extensions/permission_message_combinations_unittest.cc index 7581ff1d..42764bb 100644 --- a/chrome/browser/extensions/permission_message_combinations_unittest.cc +++ b/chrome/browser/extensions/permission_message_combinations_unittest.cc
@@ -545,7 +545,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); CreateAndInstall( "{" @@ -559,7 +559,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); CreateAndInstall( "{" @@ -573,7 +573,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computer named 127.0.0.1")); + "Exchange data with the device named 127.0.0.1")); CreateAndInstall( "{" @@ -587,7 +587,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computer named www.example.com")); + "Exchange data with the device named www.example.com")); CreateAndInstall( "{" @@ -601,7 +601,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computer named 127.0.0.1")); + "Exchange data with the device named 127.0.0.1")); CreateAndInstall( "{" @@ -615,7 +615,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); CreateAndInstall( "{" @@ -637,7 +637,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computers named: 127.0.0.1 www.bar.com " + "Exchange data with the devices named: 127.0.0.1 www.bar.com " "www.example.com www.foo.com www.google.com")); CreateAndInstall( @@ -668,7 +668,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computers named: 127.0.0.1 www.abc.com " + "Exchange data with the devices named: 127.0.0.1 www.abc.com " "www.example.com www.foo.com www.freestuff.com www.google.com " "www.mywebsite.com www.test.com")); @@ -685,7 +685,7 @@ " }" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); } // Check that permission messages are generated correctly for @@ -788,7 +788,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); CreateAndInstall( "{" @@ -806,7 +806,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); CreateAndInstall( "{" @@ -820,7 +820,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computer named foo.example.com")); + "Exchange data with the device named foo.example.com")); CreateAndInstall( "{" @@ -834,7 +834,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); CreateAndInstall( "{" @@ -851,7 +851,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computers named: foo.example.com test.ping.com")); + "Exchange data with the devices named: foo.example.com test.ping.com")); CreateAndInstall( "{" @@ -871,7 +871,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with the computers named: foo.example.com test.ping.com " + "Exchange data with the devices named: foo.example.com test.ping.com " "test2.ping.com www.ping.com")); CreateAndInstall( @@ -890,7 +890,7 @@ " ]" "}"); ASSERT_TRUE(CheckManifestProducesPermissions( - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); } // Check that permission messages are generated correctly for
diff --git a/chrome/browser/favicon/favicon_handler_unittest.cc b/chrome/browser/favicon/favicon_handler_unittest.cc index 5a70ff442..e01f585 100644 --- a/chrome/browser/favicon/favicon_handler_unittest.cc +++ b/chrome/browser/favicon/favicon_handler_unittest.cc
@@ -183,6 +183,35 @@ ~TestFaviconDriver() override {} + // favicon::FaviconDriver implementation. + void FetchFavicon(const GURL& url) override { + ADD_FAILURE() << "TestFaviconDriver::FetchFavicon() " + << "should never be called in tests."; + } + + void SaveFavicon() override { + ADD_FAILURE() << "TestFaviconDriver::SaveFavicon() " + << "should never be called in tests."; + } + + gfx::Image GetFavicon() const override { + ADD_FAILURE() << "TestFaviconDriver::GetFavicon() " + << "should never be called in tests."; + return gfx::Image(); + } + + bool FaviconIsValid() const override { + ADD_FAILURE() << "TestFaviconDriver::FaviconIsValid() " + << "should never be called in tests."; + return false; + } + + bool HasPendingTasksForTest() override { + ADD_FAILURE() << "TestFaviconDriver::HasPendingTasksForTest() " + << "should never be called in tests."; + return false; + } + int StartDownload(const GURL& url, int max_bitmap_size) override { ADD_FAILURE() << "TestFaviconDriver::StartDownload() " << "should never be called in tests."; @@ -231,8 +260,6 @@ SetActiveFaviconImage(image); } - void NotifyFaviconUpdated(bool icon_url_changed) override {} - size_t num_active_favicon() const { return num_active_favicon_; } size_t num_favicon_available() const { return num_favicon_available_; } void ResetNumActiveFavicon() { num_active_favicon_ = 0; }
diff --git a/chrome/browser/favicon/favicon_tab_helper.cc b/chrome/browser/favicon/favicon_tab_helper.cc index e5e9334..177e7ba 100644 --- a/chrome/browser/favicon/favicon_tab_helper.cc +++ b/chrome/browser/favicon/favicon_tab_helper.cc
@@ -4,73 +4,13 @@ #include "chrome/browser/favicon/favicon_tab_helper.h" -#include "base/command_line.h" -#include "base/metrics/field_trial.h" -#include "base/strings/string_util.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/search.h" -#include "chrome/common/chrome_constants.h" #include "chrome/common/url_constants.h" -#include "components/bookmarks/browser/bookmark_model.h" -#include "components/favicon/content/favicon_url_util.h" -#include "components/favicon/core/favicon_driver_observer.h" -#include "components/favicon/core/favicon_handler.h" -#include "components/favicon/core/favicon_service.h" -#include "components/favicon_base/favicon_types.h" -#include "components/history/core/browser/history_service.h" -#include "content/public/browser/favicon_status.h" -#include "content/public/browser/invalidate_type.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_details.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" #include "content/public/common/favicon_url.h" -#include "ui/base/ui_base_switches.h" -#include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/image/image_skia_rep.h" - -using content::FaviconStatus; -using content::NavigationController; -using content::NavigationEntry; -using content::WebContents; - -DEFINE_WEB_CONTENTS_USER_DATA_KEY(FaviconTabHelper); - -namespace { - -// Returns whether icon NTP is enabled by experiment. -// TODO(huangs): Remove all 3 copies of this routine once Icon NTP launches. -bool IsIconNTPEnabled() { - // Note: It's important to query the field trial state first, to ensure that - // UMA reports the correct group. - const std::string group_name = base::FieldTrialList::FindFullName("IconNTP"); - using base::CommandLine; - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableIconNtp)) - return false; - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp)) - return true; - - return StartsWithASCII(group_name, "Enabled", true); -} - -#if defined(OS_ANDROID) || defined(OS_IOS) -const bool kDownloadLargestIcon = true; -const bool kEnableTouchIcon = true; -#else -const bool kDownloadLargestIcon = false; -const bool kEnableTouchIcon = false; -#endif - -} // namespace // static void FaviconTabHelper::CreateForWebContents( @@ -93,277 +33,41 @@ BookmarkModelFactory::GetForProfileIfExists(original_profile))); } -FaviconTabHelper::FaviconTabHelper(WebContents* web_contents, - favicon::FaviconService* favicon_service, - history::HistoryService* history_service, - bookmarks::BookmarkModel* bookmark_model) - : content::WebContentsObserver(web_contents), - favicon_service_(favicon_service), - history_service_(history_service), - bookmark_model_(bookmark_model) { - favicon_handler_.reset(new favicon::FaviconHandler( - favicon_service_, this, favicon::FaviconHandler::FAVICON, - kDownloadLargestIcon)); - if (kEnableTouchIcon) { - touch_icon_handler_.reset(new favicon::FaviconHandler( - favicon_service_, this, favicon::FaviconHandler::TOUCH, - kDownloadLargestIcon)); - } - if (IsIconNTPEnabled()) { - large_icon_handler_.reset(new favicon::FaviconHandler( - favicon_service_, this, favicon::FaviconHandler::LARGE, true)); - } +// static +FaviconTabHelper* FaviconTabHelper::FromWebContents( + content::WebContents* web_contents) { + return static_cast<FaviconTabHelper*>( + favicon::ContentFaviconDriver::FromWebContents(web_contents)); } -FaviconTabHelper::~FaviconTabHelper() { -} - -void FaviconTabHelper::FetchFavicon(const GURL& url) { - favicon_handler_->FetchFavicon(url); - if (touch_icon_handler_.get()) - touch_icon_handler_->FetchFavicon(url); - if (large_icon_handler_.get()) - large_icon_handler_->FetchFavicon(url); -} - -gfx::Image FaviconTabHelper::GetFavicon() const { - // Like GetTitle(), we also want to use the favicon for the last committed - // entry rather than a pending navigation entry. - const NavigationController& controller = web_contents()->GetController(); - NavigationEntry* entry = controller.GetTransientEntry(); - if (entry) - return entry->GetFavicon().image; - - entry = controller.GetLastCommittedEntry(); - if (entry) - return entry->GetFavicon().image; - return gfx::Image(); -} - -bool FaviconTabHelper::FaviconIsValid() const { - const NavigationController& controller = web_contents()->GetController(); - NavigationEntry* entry = controller.GetTransientEntry(); - if (entry) - return entry->GetFavicon().valid; - - entry = controller.GetLastCommittedEntry(); - if (entry) - return entry->GetFavicon().valid; - - return false; -} - -bool FaviconTabHelper::ShouldDisplayFavicon() { +// static +bool FaviconTabHelper::ShouldDisplayFavicon( + content::WebContents* web_contents) { // Always display a throbber during pending loads. - const NavigationController& controller = web_contents()->GetController(); + const content::NavigationController& controller = + web_contents->GetController(); if (controller.GetLastCommittedEntry() && controller.GetPendingEntry()) return true; - GURL url = web_contents()->GetURL(); + GURL url = web_contents->GetURL(); if (url.SchemeIs(content::kChromeUIScheme) && url.host() == chrome::kChromeUINewTabHost) { return false; } // No favicon on Instant New Tab Pages. - if (chrome::IsInstantNTP(web_contents())) + if (chrome::IsInstantNTP(web_contents)) return false; return true; } -void FaviconTabHelper::SaveFavicon() { - GURL active_url = GetActiveURL(); - if (active_url.is_empty()) - return; - - // Make sure the page is in history, otherwise adding the favicon does - // nothing. - if (!history_service_) - return; - history_service_->AddPageNoVisitForBookmark(active_url, GetActiveTitle()); - - if (!favicon_service_) - return; - if (!GetActiveFaviconValidity()) - return; - GURL favicon_url = GetActiveFaviconURL(); - if (favicon_url.is_empty()) - return; - gfx::Image image = GetActiveFaviconImage(); - if (image.IsEmpty()) - return; - favicon_service_->SetFavicons(active_url, favicon_url, favicon_base::FAVICON, - image); -} - -void FaviconTabHelper::AddObserver(favicon::FaviconDriverObserver* observer) { - observer_list_.AddObserver(observer); -} - -void FaviconTabHelper::RemoveObserver( - favicon::FaviconDriverObserver* observer) { - observer_list_.RemoveObserver(observer); -} - -int FaviconTabHelper::StartDownload(const GURL& url, int max_image_size) { - if (favicon_service_ && favicon_service_->WasUnableToDownloadFavicon(url)) { - DVLOG(1) << "Skip Failed FavIcon: " << url; - return 0; - } - - bool bypass_cache = (bypass_cache_page_url_ == GetActiveURL()); - bypass_cache_page_url_ = GURL(); - - return web_contents()->DownloadImage( - url, true, max_image_size, bypass_cache, - base::Bind(&FaviconTabHelper::DidDownloadFavicon, - base::Unretained(this))); -} - -bool FaviconTabHelper::IsOffTheRecord() { - DCHECK(web_contents()); - return web_contents()->GetBrowserContext()->IsOffTheRecord(); -} - -bool FaviconTabHelper::IsBookmarked(const GURL& url) { - return bookmark_model_ && bookmark_model_->IsBookmarked(url); -} - -GURL FaviconTabHelper::GetActiveURL() { - NavigationEntry* entry = web_contents()->GetController().GetActiveEntry(); - return entry ? entry->GetURL() : GURL(); -} - -base::string16 FaviconTabHelper::GetActiveTitle() { - NavigationEntry* entry = web_contents()->GetController().GetActiveEntry(); - return entry ? entry->GetTitle() : base::string16(); -} - -bool FaviconTabHelper::GetActiveFaviconValidity() { - return GetFaviconStatus().valid; -} - -void FaviconTabHelper::SetActiveFaviconValidity(bool valid) { - GetFaviconStatus().valid = valid; -} - -GURL FaviconTabHelper::GetActiveFaviconURL() { - return GetFaviconStatus().url; -} - -void FaviconTabHelper::SetActiveFaviconURL(const GURL& url) { - GetFaviconStatus().url = url; -} - -gfx::Image FaviconTabHelper::GetActiveFaviconImage() { - return GetFaviconStatus().image; -} - -void FaviconTabHelper::SetActiveFaviconImage(const gfx::Image& image) { - GetFaviconStatus().image = image; -} - -void FaviconTabHelper::OnFaviconAvailable(const gfx::Image& image, - const GURL& icon_url, - bool is_active_favicon) { - if (is_active_favicon) { - bool icon_url_changed = GetActiveFaviconURL() != icon_url; - // No matter what happens, we need to mark the favicon as being set. - SetActiveFaviconValidity(true); - SetActiveFaviconURL(icon_url); - - if (image.IsEmpty()) - return; - - SetActiveFaviconImage(image); - NotifyFaviconUpdated(icon_url_changed); - } - if (!image.IsEmpty()) { - FOR_EACH_OBSERVER(favicon::FaviconDriverObserver, observer_list_, - OnFaviconAvailable(image)); - } -} - -void FaviconTabHelper::NotifyFaviconUpdated(bool icon_url_changed) { - FOR_EACH_OBSERVER(favicon::FaviconDriverObserver, observer_list_, - OnFaviconUpdated(this, icon_url_changed)); - web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); -} - -void FaviconTabHelper::DidDownloadFavicon( - int id, - int http_status_code, - const GURL& image_url, - const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& original_bitmap_sizes) { - if (bitmaps.empty() && http_status_code == 404) { - DVLOG(1) << "Failed to Download Favicon:" << image_url; - if (favicon_service_) - favicon_service_->UnableToDownloadFavicon(image_url); - } - - favicon_handler_->OnDidDownloadFavicon(id, image_url, bitmaps, - original_bitmap_sizes); - if (touch_icon_handler_.get()) { - touch_icon_handler_->OnDidDownloadFavicon(id, image_url, bitmaps, - original_bitmap_sizes); - } - if (large_icon_handler_.get()) { - large_icon_handler_->OnDidDownloadFavicon(id, image_url, bitmaps, - original_bitmap_sizes); - } -} - -content::FaviconStatus& FaviconTabHelper::GetFaviconStatus() { - DCHECK(web_contents()->GetController().GetActiveEntry()); - return web_contents()->GetController().GetActiveEntry()->GetFavicon(); -} - -void FaviconTabHelper::DidStartNavigationToPendingEntry( - const GURL& url, - NavigationController::ReloadType reload_type) { - if (reload_type == NavigationController::NO_RELOAD || IsOffTheRecord()) - return; - - bypass_cache_page_url_ = url; - - if (favicon_service_) { - favicon_service_->SetFaviconOutOfDateForPage(url); - if (reload_type == NavigationController::RELOAD_IGNORING_CACHE) - favicon_service_->ClearUnableToDownloadFavicons(); - } -} - -void FaviconTabHelper::DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) { - favicon_urls_.clear(); - - // Wait till the user navigates to a new URL to start checking the cache - // again. The cache may be ignored for non-reload navigations (e.g. - // history.replace() in-page navigation). This is allowed to increase the - // likelihood that "reloading a page ignoring the cache" redownloads the - // favicon. In particular, a page may do an in-page navigation before - // FaviconHandler has the time to determine that the favicon needs to be - // redownloaded. - GURL url = details.entry->GetURL(); - if (url != bypass_cache_page_url_) - bypass_cache_page_url_ = GURL(); - - // Get the favicon, either from history or request it from the net. - FetchFavicon(url); -} - -void FaviconTabHelper::DidUpdateFaviconURL( - const std::vector<content::FaviconURL>& candidates) { - DCHECK(!candidates.empty()); - favicon_urls_ = candidates; - std::vector<favicon::FaviconURL> favicon_urls = - favicon::FaviconURLsFromContentFaviconURLs(candidates); - favicon_handler_->OnUpdateFaviconURL(favicon_urls); - if (touch_icon_handler_.get()) - touch_icon_handler_->OnUpdateFaviconURL(favicon_urls); - if (large_icon_handler_.get()) - large_icon_handler_->OnUpdateFaviconURL(favicon_urls); +FaviconTabHelper::FaviconTabHelper(content::WebContents* web_contents, + favicon::FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model) + : favicon::ContentFaviconDriver(web_contents, + favicon_service, + history_service, + bookmark_model) { }
diff --git a/chrome/browser/favicon/favicon_tab_helper.h b/chrome/browser/favicon/favicon_tab_helper.h index 537ee40..e907090 100644 --- a/chrome/browser/favicon/favicon_tab_helper.h +++ b/chrome/browser/favicon/favicon_tab_helper.h
@@ -5,115 +5,23 @@ #ifndef CHROME_BROWSER_FAVICON_FAVICON_TAB_HELPER_H_ #define CHROME_BROWSER_FAVICON_FAVICON_TAB_HELPER_H_ -#include <vector> +#include "base/macros.h" +#include "components/favicon/content/content_favicon_driver.h" -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/observer_list.h" -#include "components/favicon/core/favicon_driver.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" -#include "content/public/common/favicon_url.h" - -class GURL; -class SkBitmap; - -namespace gfx { -class Image; -} - -namespace bookmarks { -class BookmarkModel; -} - -namespace content { -struct FaviconStatus; -} - -namespace favicon { -class FaviconDriverObserver; -class FaviconHandler; -class FaviconService; -} - -namespace history { -class HistoryService; -} - -// FaviconTabHelper works with favicon::FaviconHandlers to fetch the favicons. -// -// FetchFavicon fetches the given page's icons. It requests the icons from the -// history backend. If the icon is not available or expired, the icon will be -// downloaded and saved in the history backend. -// -class FaviconTabHelper : public content::WebContentsObserver, - public favicon::FaviconDriver, - public content::WebContentsUserData<FaviconTabHelper> { +// FaviconTabHelper provides helper factory for ContentFaviconDriver. +class FaviconTabHelper : public favicon::ContentFaviconDriver { public: - ~FaviconTabHelper() override; - static void CreateForWebContents(content::WebContents* web_contents); - // Initiates loading the favicon for the specified url. - void FetchFavicon(const GURL& url); - - // Returns the favicon for this tab, or IDR_DEFAULT_FAVICON if the tab does - // not have a favicon. The default implementation uses the current navigation - // entry. This will return an empty bitmap if there are no navigation - // entries, which should rarely happen. - gfx::Image GetFavicon() const; - - // Returns true if we have the favicon for the page. - bool FaviconIsValid() const; + // TODO(sdefresne): remove this method once all clients have been ported to + // use ContentFaviconDriver::FromWebContents() instead. + static FaviconTabHelper* FromWebContents(content::WebContents* web_contents); // Returns whether the favicon should be displayed. If this returns false, no // space is provided for the favicon, and the favicon is never displayed. - bool ShouldDisplayFavicon(); - - // Returns the current tab's favicon urls. If this is empty, - // DidUpdateFaviconURL has not yet been called for the current navigation. - const std::vector<content::FaviconURL>& favicon_urls() const { - return favicon_urls_; - } - - // content::WebContentsObserver override. Must be public, because also - // called from PrerenderContents. - void DidUpdateFaviconURL( - const std::vector<content::FaviconURL>& candidates) override; - - // Saves the favicon for the current page. - void SaveFavicon(); - - void AddObserver(favicon::FaviconDriverObserver* observer); - void RemoveObserver(favicon::FaviconDriverObserver* observer); - - // favicon::FaviconDriver methods. - int StartDownload(const GURL& url, int max_bitmap_size) override; - bool IsOffTheRecord() override; - bool IsBookmarked(const GURL& url) override; - GURL GetActiveURL() override; - base::string16 GetActiveTitle() override; - bool GetActiveFaviconValidity() override; - void SetActiveFaviconValidity(bool valid) override; - GURL GetActiveFaviconURL() override; - void SetActiveFaviconURL(const GURL& url) override; - gfx::Image GetActiveFaviconImage() override; - void SetActiveFaviconImage(const gfx::Image& image) override; - void OnFaviconAvailable(const gfx::Image& image, - const GURL& url, - bool is_active_favicon) override; - void NotifyFaviconUpdated(bool icon_url_changed) override; - - // Favicon download callback. - void DidDownloadFavicon( - int id, - int http_status_code, - const GURL& image_url, - const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& original_bitmap_sizes); + static bool ShouldDisplayFavicon(content::WebContents* web_contents); private: - friend class content::WebContentsUserData<FaviconTabHelper>; friend class FaviconTabHelperTest; // Creates a new FaviconTabHelper bound to |web_contents|. Initialize @@ -124,37 +32,6 @@ history::HistoryService* history_service, bookmarks::BookmarkModel* bookmark_model); - // content::WebContentsObserver overrides. - void DidStartNavigationToPendingEntry( - const GURL& url, - content::NavigationController::ReloadType reload_type) override; - void DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) override; - - // Helper method that returns the active navigation entry's favicon. - content::FaviconStatus& GetFaviconStatus(); - - // KeyedService used by FaviconTabHelper. They may be null during testing, but - // if they are defined, they must outlive the FaviconTabHelper. - favicon::FaviconService* favicon_service_; - history::HistoryService* history_service_; - bookmarks::BookmarkModel* bookmark_model_; - - std::vector<content::FaviconURL> favicon_urls_; - - // Bypass cache when downloading favicons for this page URL. - GURL bypass_cache_page_url_; - - // FaviconHandlers used to download the different kind of favicons. Both - // |touch_icon_handler_| and |large_icon_handler_| may be null depending - // on the platform or variations. - scoped_ptr<favicon::FaviconHandler> favicon_handler_; - scoped_ptr<favicon::FaviconHandler> touch_icon_handler_; - scoped_ptr<favicon::FaviconHandler> large_icon_handler_; - - ObserverList<favicon::FaviconDriverObserver> observer_list_; - DISALLOW_COPY_AND_ASSIGN(FaviconTabHelper); };
diff --git a/chrome/browser/favicon/favicon_tab_helper_browsertest.cc b/chrome/browser/favicon/favicon_tab_helper_browsertest.cc index 8722b5b..567d825f 100644 --- a/chrome/browser/favicon/favicon_tab_helper_browsertest.cc +++ b/chrome/browser/favicon/favicon_tab_helper_browsertest.cc
@@ -187,11 +187,8 @@ // FaviconTabHelperPendingTaskChecker: bool HasPendingTasks() override { - favicon::FaviconHandler* favicon_handler = - FaviconTabHelper::FromWebContents(web_contents()) - ->favicon_handler_.get(); - return !favicon_handler->download_requests_.empty() || - favicon_handler->cancelable_task_tracker_.HasTrackedTasks(); + return FaviconTabHelper::FromWebContents(web_contents()) + ->HasPendingTasksForTest(); } private:
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc index 245a30b..c6de4d0 100644 --- a/chrome/browser/history/history_backend_unittest.cc +++ b/chrome/browser/history/history_backend_unittest.cc
@@ -2642,49 +2642,6 @@ EXPECT_TRUE(bitmap_results.empty()); } -TEST_F(HistoryBackendTest, CloneFaviconIsRestrictedToSameDomain) { - const GURL url("http://www.google.com/"); - const GURL same_domain_url("http://www.google.com/subdir/index.html"); - const GURL foreign_domain_url("http://www.not-google.com/"); - const GURL icon_url("http://www.google.com/icon.png"); - std::vector<SkBitmap> bitmaps; - bitmaps.push_back(CreateBitmap(SK_ColorBLUE, kSmallEdgeSize)); - - // Add a favicon - backend_->SetFavicons(url, favicon_base::FAVICON, icon_url, bitmaps); - EXPECT_TRUE(backend_->thumbnail_db_->GetIconMappingsForPageURL( - url, favicon_base::FAVICON, NULL)); - - // Validate starting state. - std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results_out; - EXPECT_TRUE(backend_->GetFaviconsFromDB(url, - favicon_base::FAVICON, - GetEdgeSizesSmallAndLarge(), - &bitmap_results_out)); - EXPECT_FALSE(backend_->GetFaviconsFromDB(same_domain_url, - favicon_base::FAVICON, - GetEdgeSizesSmallAndLarge(), - &bitmap_results_out)); - EXPECT_FALSE(backend_->GetFaviconsFromDB(foreign_domain_url, - favicon_base::FAVICON, - GetEdgeSizesSmallAndLarge(), - &bitmap_results_out)); - - // Same-domain cloning should work. - backend_->CloneFavicons(url, same_domain_url); - EXPECT_TRUE(backend_->GetFaviconsFromDB(same_domain_url, - favicon_base::FAVICON, - GetEdgeSizesSmallAndLarge(), - &bitmap_results_out)); - - // Foreign-domain cloning is forbidden. - backend_->CloneFavicons(url, foreign_domain_url); - EXPECT_FALSE(backend_->GetFaviconsFromDB(foreign_domain_url, - favicon_base::FAVICON, - GetEdgeSizesSmallAndLarge(), - &bitmap_results_out)); -} - TEST_F(HistoryBackendTest, QueryFilteredURLs) { const char* google = "http://www.google.com/"; const char* yahoo = "http://www.yahoo.com/";
diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc index fcab1eb7..9cca3cd 100644 --- a/chrome/browser/history/thumbnail_database_unittest.cc +++ b/chrome/browser/history/thumbnail_database_unittest.cc
@@ -247,34 +247,6 @@ EXPECT_EQ(last_requested, now); } -TEST_F(ThumbnailDatabaseTest, UpdateIconMapping) { - ThumbnailDatabase db(NULL); - ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); - db.BeginTransaction(); - - GURL url("http://google.com"); - favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); - - EXPECT_LT(0, db.AddIconMapping(url, id)); - std::vector<IconMapping> icon_mapping; - EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); - ASSERT_EQ(1u, icon_mapping.size()); - EXPECT_EQ(url, icon_mapping.front().page_url); - EXPECT_EQ(id, icon_mapping.front().icon_id); - - GURL url1("http://www.google.com/"); - favicon_base::FaviconID new_id = - db.AddFavicon(url1, favicon_base::TOUCH_ICON); - EXPECT_TRUE(db.UpdateIconMapping(icon_mapping.front().mapping_id, new_id)); - - icon_mapping.clear(); - EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); - ASSERT_EQ(1u, icon_mapping.size()); - EXPECT_EQ(url, icon_mapping.front().page_url); - EXPECT_EQ(new_id, icon_mapping.front().icon_id); - EXPECT_NE(id, icon_mapping.front().icon_id); -} - TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { ThumbnailDatabase db(NULL); ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); @@ -614,71 +586,6 @@ EXPECT_FALSE(db.HasMappingFor(id3)); } -TEST_F(ThumbnailDatabaseTest, CloneIconMappings) { - ThumbnailDatabase db(NULL); - ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); - db.BeginTransaction(); - - std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); - scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); - - // Add a favicon which will have icon_mappings - favicon_base::FaviconID id1 = - db.AddFavicon(GURL("http://google.com"), favicon_base::FAVICON); - EXPECT_NE(0, id1); - base::Time time = base::Time::Now(); - db.AddFaviconBitmap(id1, favicon, time, gfx::Size()); - - // Add another type of favicon - favicon_base::FaviconID id2 = db.AddFavicon( - GURL("http://www.google.com/icon"), favicon_base::TOUCH_ICON); - EXPECT_NE(0, id2); - time = base::Time::Now(); - db.AddFaviconBitmap(id2, favicon, time, gfx::Size()); - - // Add 3rd favicon - favicon_base::FaviconID id3 = db.AddFavicon( - GURL("http://www.google.com/icon"), favicon_base::TOUCH_ICON); - EXPECT_NE(0, id3); - time = base::Time::Now(); - db.AddFaviconBitmap(id3, favicon, time, gfx::Size()); - - GURL page1_url("http://page1.com"); - EXPECT_TRUE(db.AddIconMapping(page1_url, id1)); - EXPECT_TRUE(db.AddIconMapping(page1_url, id2)); - - GURL page2_url("http://page2.com"); - EXPECT_TRUE(db.AddIconMapping(page2_url, id3)); - - // Test we do nothing with existing mappings. - std::vector<IconMapping> icon_mapping; - EXPECT_TRUE(db.GetIconMappingsForPageURL(page2_url, &icon_mapping)); - ASSERT_EQ(1U, icon_mapping.size()); - - EXPECT_TRUE(db.CloneIconMappings(page1_url, page2_url)); - - icon_mapping.clear(); - EXPECT_TRUE(db.GetIconMappingsForPageURL(page2_url, &icon_mapping)); - ASSERT_EQ(1U, icon_mapping.size()); - EXPECT_EQ(page2_url, icon_mapping[0].page_url); - EXPECT_EQ(id3, icon_mapping[0].icon_id); - - // Test we clone if the new page has no mappings. - GURL page3_url("http://page3.com"); - EXPECT_TRUE(db.CloneIconMappings(page1_url, page3_url)); - - icon_mapping.clear(); - EXPECT_TRUE(db.GetIconMappingsForPageURL(page3_url, &icon_mapping)); - - ASSERT_EQ(2U, icon_mapping.size()); - if (icon_mapping[0].icon_id == id2) - std::swap(icon_mapping[0], icon_mapping[1]); - EXPECT_EQ(page3_url, icon_mapping[0].page_url); - EXPECT_EQ(id1, icon_mapping[0].icon_id); - EXPECT_EQ(page3_url, icon_mapping[1].page_url); - EXPECT_EQ(id2, icon_mapping[1].icon_id); -} - // Test loading version 3 database. TEST_F(ThumbnailDatabaseTest, Version3) { scoped_ptr<ThumbnailDatabase> db = LoadFromGolden("Favicons.v3.sql");
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index f753407..ebcdc7e 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -97,7 +97,7 @@ #endif #if defined(USE_NSS) || defined(OS_IOS) -#include "net/ocsp/nss_ocsp.h" +#include "net/cert_net/nss_ocsp.h" #endif #if defined(OS_ANDROID)
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc index afa9d30..ac9ff01f 100644 --- a/chrome/browser/lifetime/application_lifetime.cc +++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -242,9 +242,8 @@ #if defined(OS_CHROMEOS) // A function called when SIGTERM is received. void ExitCleanly() { - // We always mark exit cleanly because SessionManager may kill - // chrome in 3 seconds after SIGTERM. - g_browser_process->EndSession(); + // We always mark exit cleanly. + MarkAsCleanShutdown(); // Don't block when SIGTERM is received. AreaAllBrowsersCloseable() // can be false in following cases. a) power-off b) signout from
diff --git a/chrome/browser/media/OWNERS b/chrome/browser/media/OWNERS index 6bd9a3c..8c88c3c 100644 --- a/chrome/browser/media/OWNERS +++ b/chrome/browser/media/OWNERS
@@ -5,10 +5,10 @@ tommi@chromium.org xhwang@chromium.org +# For Cast streaming changes. per-file cast_*=hclam@chromium.org per-file cast_*=hubbe@chromium.org -per-file cast_*=mikhal@chromium.org -per-file cast_*=pwestin@google.com +per-file cast_*=miu@chromium.org # For WebRTC browser tests, etc. per-file *webrtc*browsertest*=phoglund@chromium.org
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc index cba2d99..4bfb4c9 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -28,7 +28,6 @@ #include "chrome/common/chrome_version_info.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" -#include "components/content_settings/core/browser/content_settings_provider.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/pref_registry/pref_registry_syncable.h" #include "content/public/browser/browser_thread.h" @@ -423,7 +422,7 @@ security_origin, security_origin, contentSettingsType, - NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_ALLOW) { + content_settings::ResourceIdentifier()) == CONTENT_SETTING_ALLOW) { return true; } @@ -469,7 +468,7 @@ security_origin, security_origin, contentSettingsType, - NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_ALLOW) { + content_settings::ResourceIdentifier()) == CONTENT_SETTING_ALLOW) { return true; }
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc index fb6f381..f6d6ecad 100644 --- a/chrome/browser/media/media_stream_devices_controller.cc +++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -17,7 +17,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" -#include "components/content_settings/core/browser/content_settings_provider.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" @@ -543,9 +542,11 @@ return false; } if (profile_->GetHostContentSettingsMap()->GetContentSetting( - request_.security_origin, request_.security_origin, - device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) != - CONTENT_SETTING_ALLOW) { + request_.security_origin, + request_.security_origin, + device_checks[i].settings_type, + content_settings::ResourceIdentifier()) != + CONTENT_SETTING_ALLOW) { return false; } } @@ -561,10 +562,11 @@ if (IsDeviceAudioCaptureRequestedAndAllowed()) { if (profile_->GetHostContentSettingsMap()->GetContentSetting( - request_.security_origin, - request_.security_origin, - CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, - NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) { + request_.security_origin, + request_.security_origin, + CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, + content_settings::ResourceIdentifier()) == + CONTENT_SETTING_BLOCK) { request_permissions_[content::MEDIA_DEVICE_AUDIO_CAPTURE].permission = MEDIA_BLOCKED_BY_USER_SETTING; } else { @@ -574,10 +576,11 @@ if (IsDeviceVideoCaptureRequestedAndAllowed()) { if (profile_->GetHostContentSettingsMap()->GetContentSetting( - request_.security_origin, - request_.security_origin, - CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, - NO_RESOURCE_IDENTIFIER) == CONTENT_SETTING_BLOCK) { + request_.security_origin, + request_.security_origin, + CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, + content_settings::ResourceIdentifier()) == + CONTENT_SETTING_BLOCK) { request_permissions_[content::MEDIA_DEVICE_VIDEO_CAPTURE].permission = MEDIA_BLOCKED_BY_USER_SETTING; } else {
diff --git a/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc new file mode 100644 index 0000000..6ef2d29 --- /dev/null +++ b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.cc
@@ -0,0 +1,143 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h" + +#include <stdio.h> + +#include <string> + +#include "base/metrics/histogram.h" +#include "base/metrics/sparse_histogram.h" +#include "net/http/http_response_headers.h" +#include "url/gurl.h" + +namespace mod_pagespeed { + +namespace { + +const char kModPagespeedHeader[] = "X-Mod-Pagespeed"; +const char kPageSpeedHeader[] = "X-Page-Speed"; + +// For historical reasons, mod_pagespeed usage metrics are named with a +// prerender prefix. +const char kPagespeedServerHistogram[] = + "Prerender.PagespeedHeader.ServerCounts"; +const char kPagespeedVersionHistogram[] = + "Prerender.PagespeedHeader.VersionCounts"; + +enum PagespeedHeaderServerType { + PAGESPEED_TOTAL_RESPONSES = 0, + PAGESPEED_MOD_PAGESPEED_SERVER = 1, + PAGESPEED_NGX_PAGESPEED_SERVER = 2, + PAGESPEED_PAGESPEED_SERVICE_SERVER = 3, + PAGESPEED_UNKNOWN_SERVER = 4, + PAGESPEED_SERVER_MAXIMUM = 5 +}; + +// Parse the PageSpeed version number and encodes it in buckets 2 through 99: if +// it is in the format MAJOR.MINOR.BRANCH.POINT-COMMIT the bucket will be 2 + 2 +// * (max(BRANCH, 10) - 10) + (POINT > 1 ? 1 : 0); otherwise the bucket is +// zero. +int GetXModPagespeedBucketFromVersion(const std::string& version) { + int unused_major, unused_minor, branch, point, unused_commit; + int num_parsed = sscanf(version.c_str(), "%d.%d.%d.%d-%d", &unused_major, + &unused_minor, &branch, &point, &unused_commit); + int output = 0; + if (num_parsed == 5) { + output = 2; + if (branch > 10) + output += 2 * (branch - 10); + if (point > 1) + output++; + if (output < 2 || output > 99) + output = 0; + } + return output; +} + +// Parse the X-Page-Speed header value and determine whether it is in the +// PageSpeed Service format, namely MAJOR_MINOR_AB were MAJOR_MINOR is a version +// number and AB is an encoded 2-character value. +bool IsPageSpeedServiceVersionNumber(const std::string& version) { + int major, minor; + // is_eol is to detect EOL as we check that it /isn't/ converted. + char a, b, is_eol; + int num_parsed = + sscanf(version.c_str(), "%d_%d_%c%c%c", &major, &minor, &a, &b, &is_eol); + return (num_parsed == 4); +} + +} // namespace + +void RecordMetrics(const content::ResourceType resource_type, + const GURL& request_url, + const net::HttpResponseHeaders* response_headers) { + if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME || + !request_url.SchemeIsHTTPOrHTTPS()) { + return; + } + + // Bucket 0 counts every response seen. + UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, + PAGESPEED_TOTAL_RESPONSES, + PAGESPEED_SERVER_MAXIMUM); + if (!response_headers) + return; + + void* iter = nullptr; + std::string name; + std::string value; + while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) { + if (name == kModPagespeedHeader) { + // Bucket 1 counts occurrences of the X-Mod-Pagespeed header. + UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, + PAGESPEED_MOD_PAGESPEED_SERVER, + PAGESPEED_SERVER_MAXIMUM); + if (!value.empty()) { + // If the header value is in the X-Mod-Pagespeed version number format + // then increment the appropriate bucket, otherwise increment bucket 1, + // which is the catch-all "unknown version number" bucket. + int bucket = GetXModPagespeedBucketFromVersion(value); + if (bucket > 0) { + UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); + } else { + UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, 1); + } + } + break; + } else if (name == kPageSpeedHeader) { + // X-Page-Speed header versions are either in the X-Mod-Pagespeed format, + // indicating an nginx installation, or they're in the PageSpeed Service + // format, indicating a PSS installation, or in some other format, + // indicating an unknown installation [possibly IISpeed]. + if (!value.empty()) { + int bucket = GetXModPagespeedBucketFromVersion(value); + if (bucket > 0) { + // Bucket 2 counts occurences of the X-Page-Speed header with a + // value in the X-Mod-Pagespeed version number format. We also + // count these responses in the version histogram. + UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, + PAGESPEED_NGX_PAGESPEED_SERVER, + PAGESPEED_SERVER_MAXIMUM); + UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); + } else if (IsPageSpeedServiceVersionNumber(value)) { + // Bucket 3 counts occurences of the X-Page-Speed header with a + // value in the PageSpeed Service version number format. + UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, + PAGESPEED_PAGESPEED_SERVICE_SERVER, + PAGESPEED_SERVER_MAXIMUM); + } else { + // Bucket 4 counts occurences of all other values. + UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, + PAGESPEED_UNKNOWN_SERVER, + PAGESPEED_SERVER_MAXIMUM); + } + } + break; + } + } +} + +} // namespace mod_pagespeed
diff --git a/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h new file mode 100644 index 0000000..16831b13 --- /dev/null +++ b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h
@@ -0,0 +1,28 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MOD_PAGESPEED_MOD_PAGESPEED_METRICS_H_ +#define CHROME_BROWSER_MOD_PAGESPEED_MOD_PAGESPEED_METRICS_H_ + +#include "content/public/common/resource_type.h" + +class GURL; + +namespace net { +class HttpResponseHeaders; +} + +namespace mod_pagespeed { + +// Records metrics about mod_pagespeed headers. +// +// See +// https://developers.google.com/speed/pagespeed/module/configuration#XHeaderValue +void RecordMetrics(const content::ResourceType resource_type, + const GURL& request_url, + const net::HttpResponseHeaders* response_headers); + +} // namespace mod_pagespeed + +#endif // CHROME_BROWSER_MOD_PAGESPEED_MOD_PAGESPEED_METRICS_H_
diff --git a/chrome/browser/mod_pagespeed/mod_pagespeed_metrics_unittest.cc b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics_unittest.cc new file mode 100644 index 0000000..38ef0cb --- /dev/null +++ b/chrome/browser/mod_pagespeed/mod_pagespeed_metrics_unittest.cc
@@ -0,0 +1,166 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h" + +#include <algorithm> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_samples.h" +#include "base/metrics/statistics_recorder.h" +#include "content/public/common/resource_type.h" +#include "net/http/http_response_headers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace mod_pagespeed { + +// Ensure that we count PageSpeed headers correctly. +TEST(ModPagespeedMetricsTest, CountPageSpeedHeadersTest) { + base::StatisticsRecorder::Initialize(); + GURL url("http://google.com"); + std::string temp("HTTP/1.1 200 OK\n\n"); + std::replace(temp.begin(), temp.end(), '\n', '\0'); + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders(temp)); + + int num_responses = 0; + int num_mps = 0; + int num_ngx = 0; + int num_pss = 0; + int num_other = 0; + int num_bucket_1 = 0; // unrecognized format/value bucket + int num_bucket_30 = 0; // 1.2.24.1 bucket + int num_bucket_33 = 0; // 1.3.25.2 bucket + + scoped_ptr<base::HistogramSamples> server_samples; + scoped_ptr<base::HistogramSamples> version_samples; + + // No PageSpeed header. The VersionCounts histogram isn't created yet. + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); + base::HistogramBase* server_histogram = + base::StatisticsRecorder::FindHistogram( + "Prerender.PagespeedHeader.ServerCounts"); + ASSERT_TRUE(server_histogram != NULL); + ASSERT_TRUE(NULL == base::StatisticsRecorder::FindHistogram( + "Prerender.PagespeedHeader.VersionCounts")); + + server_samples = server_histogram->SnapshotSamples(); + EXPECT_EQ(++num_responses, server_samples->GetCount(0)); + EXPECT_EQ(num_mps, server_samples->GetCount(1)); + EXPECT_EQ(num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(num_other, server_samples->GetCount(4)); + + // X-Mod-Pagespeed header in expected format. VersionCounts now exists. + headers->AddHeader("X-Mod-Pagespeed: 1.2.24.1-2300"); + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); + base::HistogramBase* version_histogram = + base::StatisticsRecorder::FindHistogram( + "Prerender.PagespeedHeader.VersionCounts"); + ASSERT_TRUE(version_histogram != NULL); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(++num_responses, server_samples->GetCount(0)); + EXPECT_EQ(++num_mps, server_samples->GetCount(1)); + EXPECT_EQ(num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(num_other, server_samples->GetCount(4)); + EXPECT_EQ(num_bucket_1, version_samples->GetCount(1)); + EXPECT_EQ(++num_bucket_30, version_samples->GetCount(30)); // +1 for #30 + EXPECT_EQ(num_bucket_33, version_samples->GetCount(33)); + headers->RemoveHeader("X-Mod-Pagespeed"); + + // X-Mod-Pagespeed header in unexpected format. + headers->AddHeader("X-Mod-Pagespeed: Powered By PageSpeed!"); + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(++num_responses, server_samples->GetCount(0)); + EXPECT_EQ(++num_mps, server_samples->GetCount(1)); + EXPECT_EQ(num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(num_other, server_samples->GetCount(4)); + EXPECT_EQ(++num_bucket_1, version_samples->GetCount(1)); // +1 for 'huh?' + EXPECT_EQ(num_bucket_30, version_samples->GetCount(30)); + EXPECT_EQ(num_bucket_33, version_samples->GetCount(33)); + headers->RemoveHeader("X-Mod-Pagespeed"); + + // X-Page-Speed header in mod_pagespeed format (so ngx_pagespeed). + headers->AddHeader("X-Page-Speed: 1.3.25.2-2530"); + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(++num_responses, server_samples->GetCount(0)); + EXPECT_EQ(num_mps, server_samples->GetCount(1)); + EXPECT_EQ(++num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(num_other, server_samples->GetCount(4)); + EXPECT_EQ(num_bucket_1, version_samples->GetCount(1)); + EXPECT_EQ(num_bucket_30, version_samples->GetCount(30)); + EXPECT_EQ(++num_bucket_33, version_samples->GetCount(33)); // +1 for #33 + headers->RemoveHeader("X-Page-Speed"); + + // X-Page-Speed header in PageSpeed Service format. + headers->AddHeader("X-Page-Speed: 97_4_bo"); + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(++num_responses, server_samples->GetCount(0)); + EXPECT_EQ(num_mps, server_samples->GetCount(1)); // no change + EXPECT_EQ(num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(++num_pss, server_samples->GetCount(3)); // +1 for PSS + EXPECT_EQ(num_other, server_samples->GetCount(4)); + EXPECT_EQ(num_bucket_1, version_samples->GetCount(1)); + EXPECT_EQ(num_bucket_30, version_samples->GetCount(30)); + EXPECT_EQ(num_bucket_33, version_samples->GetCount(33)); + headers->RemoveHeader("X-Page-Speed"); + + // X-Page-Speed header in an unrecognized format (IISpeed in this case). + headers->AddHeader("X-Page-Speed: 1.0PS1.2-20130615"); + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(++num_responses, server_samples->GetCount(0)); + EXPECT_EQ(num_mps, server_samples->GetCount(1)); // no change + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(++num_other, server_samples->GetCount(4)); // +1 for 'other' + EXPECT_EQ(num_bucket_1, version_samples->GetCount(1)); + EXPECT_EQ(num_bucket_30, version_samples->GetCount(30)); + EXPECT_EQ(num_bucket_33, version_samples->GetCount(33)); + + // Not a main frame => not counted at all. + RecordMetrics(content::RESOURCE_TYPE_SUB_FRAME, url, headers.get()); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(num_responses, server_samples->GetCount(0)); + EXPECT_EQ(num_mps, server_samples->GetCount(1)); + EXPECT_EQ(num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(num_other, server_samples->GetCount(4)); + EXPECT_EQ(num_bucket_1, version_samples->GetCount(1)); + EXPECT_EQ(num_bucket_30, version_samples->GetCount(30)); + EXPECT_EQ(num_bucket_33, version_samples->GetCount(33)); + + // Not a http/https URL => not counted at all. + GURL data_url("data:image/png;base64,yadda yadda=="); + RecordMetrics(content::RESOURCE_TYPE_MAIN_FRAME, data_url, headers.get()); + server_samples = server_histogram->SnapshotSamples(); + version_samples = version_histogram->SnapshotSamples(); + EXPECT_EQ(num_responses, server_samples->GetCount(0)); + EXPECT_EQ(num_mps, server_samples->GetCount(1)); + EXPECT_EQ(num_ngx, server_samples->GetCount(2)); + EXPECT_EQ(num_pss, server_samples->GetCount(3)); + EXPECT_EQ(num_other, server_samples->GetCount(4)); + EXPECT_EQ(num_bucket_1, version_samples->GetCount(1)); + EXPECT_EQ(num_bucket_30, version_samples->GetCount(30)); + EXPECT_EQ(num_bucket_33, version_samples->GetCount(33)); + + headers->RemoveHeader("X-Page-Speed"); +} + +} // namespace mod_pagespeed
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc index 4b2ccb8..284294b2 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_settings_android.cc
@@ -11,7 +11,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/pref_names.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "jni/DataReductionProxySettings_jni.h" @@ -113,7 +113,7 @@ jlongArray result = env->NewLongArray( data_reduction_proxy::kNumDaysInHistory); - DataReductionProxySettings::ContentLengthList lengths = + data_reduction_proxy::ContentLengthList lengths = Settings()->GetDailyContentLengths(pref_name); if (!lengths.empty()) {
diff --git a/chrome/browser/net/websocket_browsertest.cc b/chrome/browser/net/websocket_browsertest.cc index c96e38b..ed1fa0b9 100644 --- a/chrome/browser/net/websocket_browsertest.cc +++ b/chrome/browser/net/websocket_browsertest.cc
@@ -300,20 +300,25 @@ IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, WebSocketAppliesHSTS) { net::SpawnedTestServer https_server( net::SpawnedTestServer::TYPE_HTTPS, - net::SpawnedTestServer::SSLOptions(), + net::SpawnedTestServer::SSLOptions( + net::SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN), base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); - // This test sets HSTS on 127.0.0.1. To avoid being redirected to https, start - // the http server on "localhost" instead. + net::SpawnedTestServer wss_server( + net::SpawnedTestServer::TYPE_WSS, + net::SpawnedTestServer::SSLOptions( + net::SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN), + net::GetWebSocketTestDataDirectory()); + // This test sets HSTS on localhost. To avoid being redirected to https, start + // the http server on 127.0.0.1 instead. net::SpawnedTestServer http_server( - net::SpawnedTestServer::TYPE_HTTP, - "localhost", + net::SpawnedTestServer::TYPE_HTTP, net::SpawnedTestServer::kLocalhost, base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); ASSERT_TRUE(https_server.StartInBackground()); ASSERT_TRUE(http_server.StartInBackground()); - ASSERT_TRUE(wss_server_.StartInBackground()); + ASSERT_TRUE(wss_server.StartInBackground()); ASSERT_TRUE(https_server.BlockUntilStarted()); - // Set HSTS on 127.0.0.1. + // Set HSTS on localhost. content::TitleWatcher title_watcher( browser()->tab_strip_model()->GetActiveWebContents(), base::ASCIIToUTF16("SET")); @@ -323,8 +328,8 @@ EXPECT_TRUE(EqualsASCII(result, "SET")); // Verify that it applies to WebSockets. - ASSERT_TRUE(wss_server_.BlockUntilStarted()); - GURL wss_url = wss_server_.GetURL("echo-with-no-extension"); + ASSERT_TRUE(wss_server.BlockUntilStarted()); + GURL wss_url = wss_server.GetURL("echo-with-no-extension"); std::string scheme("ws"); GURL::Replacements scheme_replacement; scheme_replacement.SetSchemeStr(scheme);
diff --git a/chrome/browser/notifications/desktop_notification_profile_util.cc b/chrome/browser/notifications/desktop_notification_profile_util.cc index c822779..2a004193 100644 --- a/chrome/browser/notifications/desktop_notification_profile_util.cc +++ b/chrome/browser/notifications/desktop_notification_profile_util.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/notifications/desktop_notification_profile_util.h" #include "chrome/browser/profiles/profile.h" -#include "components/content_settings/core/browser/content_settings_provider.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_pattern.h" @@ -19,12 +18,9 @@ void DesktopNotificationProfileUtil::ClearSetting( Profile* profile, const ContentSettingsPattern& pattern) { profile->GetHostContentSettingsMap()->SetContentSetting( - pattern, - ContentSettingsPattern::Wildcard(), + pattern, ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - NO_RESOURCE_IDENTIFIER, - CONTENT_SETTING_DEFAULT); - + content_settings::ResourceIdentifier(), CONTENT_SETTING_DEFAULT); } // Methods to setup and modify permission preferences. @@ -33,11 +29,9 @@ ContentSettingsPattern primary_pattern = ContentSettingsPattern::FromURLNoWildcard(origin); profile->GetHostContentSettingsMap()->SetContentSetting( - primary_pattern, - ContentSettingsPattern::Wildcard(), + primary_pattern, ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - NO_RESOURCE_IDENTIFIER, - CONTENT_SETTING_ALLOW); + content_settings::ResourceIdentifier(), CONTENT_SETTING_ALLOW); } void DesktopNotificationProfileUtil::DenyPermission( @@ -45,26 +39,21 @@ ContentSettingsPattern primary_pattern = ContentSettingsPattern::FromURLNoWildcard(origin); profile->GetHostContentSettingsMap()->SetContentSetting( - primary_pattern, - ContentSettingsPattern::Wildcard(), + primary_pattern, ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - NO_RESOURCE_IDENTIFIER, - CONTENT_SETTING_BLOCK); + content_settings::ResourceIdentifier(), CONTENT_SETTING_BLOCK); } void DesktopNotificationProfileUtil::GetNotificationsSettings( Profile* profile, ContentSettingsForOneType* settings) { profile->GetHostContentSettingsMap()->GetSettingsForOneType( CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - NO_RESOURCE_IDENTIFIER, - settings); + content_settings::ResourceIdentifier(), settings); } ContentSetting DesktopNotificationProfileUtil::GetContentSetting( Profile* profile, const GURL& origin) { return profile->GetHostContentSettingsMap()->GetContentSetting( - origin, - origin, - CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - NO_RESOURCE_IDENTIFIER); + origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, + content_settings::ResourceIdentifier()); }
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 8b81369..5b0608c1 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -179,7 +179,7 @@ origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - NO_RESOURCE_IDENTIFIER); + content_settings::ResourceIdentifier()); if (setting == CONTENT_SETTING_ALLOW) return blink::WebNotificationPermissionAllowed;
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index fca96ee3..3e90c9c 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -229,8 +229,6 @@ ManagePasswordsUIController::FromWebContents(web_contents()); manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save.Pass()); } else { - // TODO(melandory): If type is CREDENTIAL_SOURCE_API then new bubble should - // be shown. std::string uma_histogram_suffix( password_manager::metrics_util::GroupIdToString( password_manager::metrics_util::MonitoredDomainGroupId(
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_unittest.cc b/chrome/browser/password_manager/save_password_infobar_delegate_unittest.cc index 4e9d55d6..26baf83 100644 --- a/chrome/browser/password_manager/save_password_infobar_delegate_unittest.cc +++ b/chrome/browser/password_manager/save_password_infobar_delegate_unittest.cc
@@ -54,11 +54,11 @@ void TearDown() override; const autofill::PasswordForm& test_form() { return test_form_; } - MockPasswordFormManager* CreateMockFormManager(); + scoped_ptr<MockPasswordFormManager> CreateMockFormManager(); protected: scoped_ptr<ConfirmInfoBarDelegate> CreateDelegate( - MockPasswordFormManager* password_form_manager, + scoped_ptr<password_manager::PasswordFormManager> password_form_manager, password_manager::CredentialSourceType type); password_manager::StubPasswordManagerClient client_; @@ -74,20 +74,18 @@ test_form_.password_value = base::ASCIIToUTF16("12345"); } -MockPasswordFormManager* +scoped_ptr<MockPasswordFormManager> SavePasswordInfoBarDelegateTest::CreateMockFormManager() { - return new MockPasswordFormManager(&client_, test_form()); + return scoped_ptr<MockPasswordFormManager>( + new MockPasswordFormManager(&client_, test_form())); } scoped_ptr<ConfirmInfoBarDelegate> SavePasswordInfoBarDelegateTest::CreateDelegate( - MockPasswordFormManager* password_form_manager, + scoped_ptr<password_manager::PasswordFormManager> password_form_manager, password_manager::CredentialSourceType type) { scoped_ptr<ConfirmInfoBarDelegate> delegate( - new TestSavePasswordInfobarDelegate( - scoped_ptr<password_manager::PasswordFormManager>( - password_form_manager), - type)); + new TestSavePasswordInfobarDelegate(password_form_manager.Pass(), type)); return delegate.Pass(); } @@ -100,26 +98,24 @@ } TEST_F(SavePasswordInfoBarDelegateTest, CancelTestCredentialSourceAPI) { - // SavePasswordInfoBarDelegate::Create takes ownership of - // password_form_manager_ptr; - MockPasswordFormManager* password_form_manager_ptr = CreateMockFormManager(); - scoped_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate( - password_form_manager_ptr, - password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API)); - EXPECT_CALL(*password_form_manager_ptr, PermanentlyBlacklist()) + scoped_ptr<MockPasswordFormManager> password_form_manager( + CreateMockFormManager()); + EXPECT_CALL(*password_form_manager.get(), PermanentlyBlacklist()) .Times(testing::Exactly(0)); + scoped_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate( + password_form_manager.Pass(), + password_manager::CredentialSourceType::CREDENTIAL_SOURCE_API)); EXPECT_TRUE(infobar->Cancel()); } TEST_F(SavePasswordInfoBarDelegateTest, CancelTestCredentialSourcePasswordManager) { - // SavePasswordInfoBarDelegate::Create takes ownership of - // password_form_manager_ptr; - MockPasswordFormManager* password_form_manager_ptr = CreateMockFormManager(); - scoped_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate( - password_form_manager_ptr, password_manager::CredentialSourceType:: - CREDENTIAL_SOURCE_PASSWORD_MANAGER)); - EXPECT_CALL(*password_form_manager_ptr, PermanentlyBlacklist()) + scoped_ptr<MockPasswordFormManager> password_form_manager( + CreateMockFormManager()); + EXPECT_CALL(*password_form_manager.get(), PermanentlyBlacklist()) .Times(testing::Exactly(1)); + scoped_ptr<ConfirmInfoBarDelegate> infobar(CreateDelegate( + password_form_manager.Pass(), password_manager::CredentialSourceType:: + CREDENTIAL_SOURCE_PASSWORD_MANAGER)); EXPECT_TRUE(infobar->Cancel()); }
diff --git a/chrome/browser/plugins/plugin_info_message_filter.cc b/chrome/browser/plugins/plugin_info_message_filter.cc index c50d1c26..657357c7 100644 --- a/chrome/browser/plugins/plugin_info_message_filter.cc +++ b/chrome/browser/plugins/plugin_info_message_filter.cc
@@ -282,7 +282,7 @@ ChromeViewHostMsg_GetPluginInfo::WriteReplyParams(reply_msg, output); Send(reply_msg); - if (output.status.value != + if (output.status != ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) { main_thread_task_runner_->PostTask( FROM_HERE, base::Bind(&ReportMetrics, output.actual_mime_type, @@ -336,8 +336,7 @@ #if defined(OS_WIN) if (plugin.type == WebPluginInfo::PLUGIN_TYPE_NPAPI && base::win::IsMetroProcess()) { - status->value = - ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; return; } #endif @@ -347,8 +346,7 @@ #if defined(ENABLE_EXTENSIONS) if (extensions::WebViewRendererState::GetInstance()->IsGuest( render_process_id_)) { - status->value = - ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; return; } #endif @@ -376,10 +374,9 @@ if (plugin_status == PluginMetadata::SECURITY_STATUS_OUT_OF_DATE && !allow_outdated_plugins_.GetValue()) { if (allow_outdated_plugins_.IsManaged()) { - status->value = - ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed; } else { - status->value = ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked; } return; } @@ -403,7 +400,7 @@ group_policy != PluginPrefs::POLICY_ENABLED && !ChromePluginServiceFilter::GetInstance()->IsPluginRestricted( plugin.path)) { - status->value = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized; return; } @@ -412,7 +409,7 @@ !always_authorize_plugins_.GetValue() && plugin_setting != CONTENT_SETTING_BLOCK && uses_default_content_setting) { - status->value = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized; return; } @@ -428,15 +425,14 @@ #endif // defined(ENABLE_EXTENSIONS) if (plugin_setting == CONTENT_SETTING_DETECT_IMPORTANT_CONTENT) { - status->value = - ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent; } else if (plugin_setting == CONTENT_SETTING_BLOCK) { - status->value = - is_managed ? ChromeViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy - : ChromeViewHostMsg_GetPluginInfo_Status::kBlocked; + *status = is_managed + ? ChromeViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy + : ChromeViewHostMsg_GetPluginInfo_Status::kBlocked; } - if (status->value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed) { + if (*status == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed) { // Allow an embedder of <webview> to block a plugin from being loaded inside // the guest. In order to do this, set the status to 'Unauthorized' here, // and update the status as appropriate depending on the response from the @@ -444,7 +440,7 @@ #if defined(ENABLE_EXTENSIONS) if (extensions::WebViewRendererState::GetInstance()->IsGuest( render_process_id_)) - status->value = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized; #endif } @@ -459,13 +455,15 @@ WebPluginInfo* plugin, std::string* actual_mime_type, scoped_ptr<PluginMetadata>* plugin_metadata) const { + *status = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; + bool allow_wildcard = true; std::vector<WebPluginInfo> matching_plugins; std::vector<std::string> mime_types; PluginService::GetInstance()->GetPluginInfoArray( url, mime_type, allow_wildcard, &matching_plugins, &mime_types); if (matching_plugins.empty()) { - status->value = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; return false; } @@ -488,7 +486,7 @@ if (!enabled) { // Otherwise, we only found disabled plugins, so we take the first one. i = 0; - status->value = ChromeViewHostMsg_GetPluginInfo_Status::kDisabled; + *status = ChromeViewHostMsg_GetPluginInfo_Status::kDisabled; } *plugin = matching_plugins[i]; @@ -556,11 +554,10 @@ } void PluginInfoMessageFilter::Context::MaybeGrantAccess( - const ChromeViewHostMsg_GetPluginInfo_Status& status, + ChromeViewHostMsg_GetPluginInfo_Status status, const base::FilePath& path) const { - if (status.value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed || - status.value == - ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent) { + if (status == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed || + status == ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent) { ChromePluginServiceFilter::GetInstance()->AuthorizePlugin( render_process_id_, path); }
diff --git a/chrome/browser/plugins/plugin_info_message_filter.h b/chrome/browser/plugins/plugin_info_message_filter.h index a9d29a9..36eeaf5 100644 --- a/chrome/browser/plugins/plugin_info_message_filter.h +++ b/chrome/browser/plugins/plugin_info_message_filter.h
@@ -18,7 +18,7 @@ #include "content/public/browser/browser_message_filter.h" struct ChromeViewHostMsg_GetPluginInfo_Output; -struct ChromeViewHostMsg_GetPluginInfo_Status; +enum class ChromeViewHostMsg_GetPluginInfo_Status; class GURL; class HostContentSettingsMap; class PluginFinder; @@ -66,7 +66,7 @@ ContentSetting* setting, bool* is_default, bool* is_managed) const; - void MaybeGrantAccess(const ChromeViewHostMsg_GetPluginInfo_Status& status, + void MaybeGrantAccess(ChromeViewHostMsg_GetPluginInfo_Status status, const base::FilePath& path) const; bool IsPluginEnabled(const content::WebPluginInfo& plugin) const;
diff --git a/chrome/browser/plugins/plugin_info_message_filter_unittest.cc b/chrome/browser/plugins/plugin_info_message_filter_unittest.cc index a1cf28a0..6d85e97 100644 --- a/chrome/browser/plugins/plugin_info_message_filter_unittest.cc +++ b/chrome/browser/plugins/plugin_info_message_filter_unittest.cc
@@ -168,7 +168,7 @@ EXPECT_TRUE(context()->FindEnabledPlugin( 0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type, NULL)); - EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value); + EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status); EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value()); } @@ -180,7 +180,7 @@ EXPECT_TRUE(context()->FindEnabledPlugin( 0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type, NULL)); - EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value); + EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status); EXPECT_EQ(bar_plugin_path_.value(), plugin.path.value()); } @@ -194,7 +194,7 @@ EXPECT_FALSE(context()->FindEnabledPlugin( 0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type, NULL)); - EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kDisabled, status.value); + EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kDisabled, status); EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value()); } { @@ -204,7 +204,7 @@ EXPECT_FALSE(context()->FindEnabledPlugin( 0, GURL(), GURL(), "baz/blurp", &status, &plugin, &actual_mime_type, NULL)); - EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kNotFound, status.value); + EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kNotFound, status); EXPECT_EQ(FILE_PATH_LITERAL(""), plugin.path.value()); } }
diff --git a/chrome/browser/plugins/plugin_observer.cc b/chrome/browser/plugins/plugin_observer.cc index e3808c6..1b56a3f 100644 --- a/chrome/browser/plugins/plugin_observer.cc +++ b/chrome/browser/plugins/plugin_observer.cc
@@ -336,17 +336,6 @@ IPC_BEGIN_MESSAGE_MAP(PluginObserver, message) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin, OnBlockedOutdatedPlugin) - IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NPAPINotSupported, - OnNPAPINotSupported) - - IPC_MESSAGE_UNHANDLED(return false) - IPC_END_MESSAGE_MAP() - - return true; -} - -bool PluginObserver::OnMessageReceived(const IPC::Message& message) { - IPC_BEGIN_MESSAGE_MAP(PluginObserver, message) #if defined(ENABLE_PLUGIN_INSTALLATION) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemovePluginPlaceholderHost, OnRemovePluginPlaceholderHost) @@ -355,6 +344,8 @@ OnOpenAboutPlugins) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CouldNotLoadPlugin, OnCouldNotLoadPlugin) + IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NPAPINotSupported, + OnNPAPINotSupported) IPC_MESSAGE_UNHANDLED(return false) IPC_END_MESSAGE_MAP()
diff --git a/chrome/browser/plugins/plugin_observer.h b/chrome/browser/plugins/plugin_observer.h index 1e46bd7..240bc7c 100644 --- a/chrome/browser/plugins/plugin_observer.h +++ b/chrome/browser/plugins/plugin_observer.h
@@ -42,7 +42,6 @@ base::ProcessId plugin_pid) override; bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) override; - bool OnMessageReceived(const IPC::Message& message) override; private: explicit PluginObserver(content::WebContents* web_contents);
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 0864a1b..a4b1ffa 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -466,6 +466,9 @@ { key::kCaptivePortalAuthenticationIgnoresProxy, prefs::kCaptivePortalAuthenticationIgnoresProxy, base::Value::TYPE_BOOLEAN }, + { key::kForceMaximizeOnFirstRun, + prefs::kForceMaximizeOnFirstRun, + base::Value::TYPE_BOOLEAN }, #endif // defined(OS_CHROMEOS) #if !defined(OS_MACOSX) && !defined(OS_CHROMEOS)
diff --git a/chrome/browser/policy/policy_startup_browsertest.cc b/chrome/browser/policy/policy_startup_browsertest.cc new file mode 100644 index 0000000..bf429d3 --- /dev/null +++ b/chrome/browser/policy/policy_startup_browsertest.cc
@@ -0,0 +1,46 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Warning: this file will not be compiled for ChromeOS because the test +// PolicyMakeDefaultBrowserTest is not valid for this platform. + +#include "base/command_line.h" +#include "chrome/common/chrome_result_codes.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/policy/core/browser/browser_policy_connector.h" +#include "components/policy/core/common/mock_configuration_policy_provider.h" +#include "components/policy/core/common/policy_map.h" +#include "policy/policy_constants.h" + +class PolicyMakeDefaultBrowserTest : public InProcessBrowserTest { + protected: + PolicyMakeDefaultBrowserTest() : InProcessBrowserTest() { + set_expected_exit_code(chrome::RESULT_CODE_ACTION_DISALLOWED_BY_POLICY); + } + + void SetUpInProcessBrowserTestFixture() override { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kMakeDefaultBrowser); + EXPECT_CALL(provider_, IsInitializationComplete(testing::_)) + .WillRepeatedly(testing::Return(true)); + + policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); + + policy::PolicyMap values; + values.Set(policy::key::kDefaultBrowserSettingEnabled, + policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, + new base::FundamentalValue(false), + NULL); + provider_.UpdateChromePolicy(values); + } + + private: + policy::MockConfigurationPolicyProvider provider_; + DISALLOW_COPY_AND_ASSIGN(PolicyMakeDefaultBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(PolicyMakeDefaultBrowserTest, MakeDefaultDisabled) { +}
diff --git a/chrome/browser/prerender/prerender_util.cc b/chrome/browser/prerender/prerender_util.cc index e7ae9d10..1081f5b 100644 --- a/chrome/browser/prerender/prerender_util.cc +++ b/chrome/browser/prerender/prerender_util.cc
@@ -22,53 +22,6 @@ namespace { -const char kModPagespeedHeader[] = "X-Mod-Pagespeed"; -const char kPageSpeedHeader[] = "X-Page-Speed"; -const char kPagespeedServerHistogram[] = - "Prerender.PagespeedHeader.ServerCounts"; -const char kPagespeedVersionHistogram[] = - "Prerender.PagespeedHeader.VersionCounts"; - -enum PagespeedHeaderServerType { - PAGESPEED_TOTAL_RESPONSES = 0, - PAGESPEED_MOD_PAGESPEED_SERVER = 1, - PAGESPEED_NGX_PAGESPEED_SERVER = 2, - PAGESPEED_PAGESPEED_SERVICE_SERVER = 3, - PAGESPEED_UNKNOWN_SERVER = 4, - PAGESPEED_SERVER_MAXIMUM = 5 -}; - -// Private function to parse the PageSpeed version number and encode it in -// buckets 2 through 99: if it is in the format a.b.c.d-e the bucket will be -// 2 + 2 * (max(c, 10) - 10) + (d > 1 ? 1 : 0); if it is not in this format -// we return zero. -int GetXModPagespeedBucketFromVersion(const std::string& version) { - int a, b, c, d, e; - int num_parsed = sscanf(version.c_str(), "%d.%d.%d.%d-%d", - &a, &b, &c, &d, &e); - int output = 0; - if (num_parsed == 5) { - output = 2; - if (c > 10) - output += 2 * (c - 10); - if (d > 1) - output++; - if (output < 2 || output > 99) - output = 0; - } - return output; -} - -// Private function to parse the X-Page-Speed header value and determine -// whether it is in the PageSpeed Service format, namely m_n_dc were m_n is -// a version number and dc is an encoded 2-character value. -bool IsPageSpeedServiceVersionNumber(const std::string& version) { - int a, b; - char c, d, e; // e is to detect EOL as we check that it /isn't/ converted. - int num_parsed = sscanf(version.c_str(), "%d_%d_%c%c%c", &a, &b, &c, &d, &e); - return (num_parsed == 4); -} - enum PrerenderSchemeCancelReason { PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL, PRERENDER_SCHEME_CANCEL_REASON_DATA, @@ -163,82 +116,6 @@ return experiment_id == 7 || experiment_id == 8; } -void GatherPagespeedData(const ResourceType resource_type, - const GURL& request_url, - const net::HttpResponseHeaders* response_headers) { - if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME || - !request_url.SchemeIsHTTPOrHTTPS()) - return; - - // bucket 0 counts every response seen. - UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, - PAGESPEED_TOTAL_RESPONSES, - PAGESPEED_SERVER_MAXIMUM); - if (!response_headers) - return; - - void* iter = NULL; - std::string name; - std::string value; - while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) { - if (name == kModPagespeedHeader) { - // Bucket 1 counts occurences of the X-Mod-Pagespeed header. - UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, - PAGESPEED_MOD_PAGESPEED_SERVER, - PAGESPEED_SERVER_MAXIMUM); - if (!value.empty()) { - // If the header value is in the X-Mod-Pagespeed version number format - // then increment the appropriate bucket, otherwise increment bucket 1, - // which is the catch-all "unknown version number" bucket. - int bucket = GetXModPagespeedBucketFromVersion(value); - if (bucket > 0) { - UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); - } else { - UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, 1); - } - } - break; - } else if (name == kPageSpeedHeader) { - // X-Page-Speed header versions are either in the X-Mod-Pagespeed format, - // indicating an nginx installation, or they're in the PageSpeed Service - // format, indicating a PSS installation, or in some other format, - // indicating an unknown installation [possibly IISpeed]. - if (!value.empty()) { - int bucket = GetXModPagespeedBucketFromVersion(value); - if (bucket > 0) { - // Bucket 2 counts occurences of the X-Page-Speed header with a - // value in the X-Mod-Pagespeed version number format. We also - // count these responses in the version histogram. - UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, - PAGESPEED_NGX_PAGESPEED_SERVER, - PAGESPEED_SERVER_MAXIMUM); - UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); - } else if (IsPageSpeedServiceVersionNumber(value)) { - // Bucket 3 counts occurences of the X-Page-Speed header with a - // value in the PageSpeed Service version number format. - UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, - PAGESPEED_PAGESPEED_SERVICE_SERVER, - PAGESPEED_SERVER_MAXIMUM); - } else { - // Bucket 4 counts occurences of all other values. - UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, - PAGESPEED_UNKNOWN_SERVER, - PAGESPEED_SERVER_MAXIMUM); - } - } - break; - } - } -} - -void URLRequestResponseStarted(net::URLRequest* request) { - const content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - GatherPagespeedData(info->GetResourceType(), - request->url(), - request->response_headers()); -} - void ReportPrerenderExternalURL() { ReportPrerenderSchemeCancelReason( PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL);
diff --git a/chrome/browser/prerender/prerender_util.h b/chrome/browser/prerender/prerender_util.h index 7394501f..6dae141e 100644 --- a/chrome/browser/prerender/prerender_util.h +++ b/chrome/browser/prerender/prerender_util.h
@@ -6,14 +6,8 @@ #define CHROME_BROWSER_PRERENDER_PRERENDER_UTIL_H_ #include "base/basictypes.h" -#include "content/public/common/resource_type.h" #include "url/gurl.h" -namespace net { -class HttpResponseHeaders; -class URLRequest; -} - namespace prerender { extern const char kChromeNavigateExtraDataKey[]; @@ -48,17 +42,6 @@ // iff this is the case for the experiment_id specified. bool IsControlGroupExperiment(uint8 experiment_id); -// Called by URLRequestResponseStarted to gather data about Pagespeed headers -// into the Prerender.PagespeedHeader histogram. Public so it can be accessed -// by the unit test. -void GatherPagespeedData(const content::ResourceType resource_type, - const GURL& request_url, - const net::HttpResponseHeaders* response_headers); - -// Static method gathering stats about a URLRequest for which a response has -// just started. -void URLRequestResponseStarted(net::URLRequest* request); - // Report a URL was canceled due to trying to handle an external URL. void ReportPrerenderExternalURL();
diff --git a/chrome/browser/prerender/prerender_util_unittest.cc b/chrome/browser/prerender/prerender_util_unittest.cc index 528eec8..ebfea81 100644 --- a/chrome/browser/prerender/prerender_util_unittest.cc +++ b/chrome/browser/prerender/prerender_util_unittest.cc
@@ -4,31 +4,27 @@ #include "chrome/browser/prerender/prerender_util.h" -#include "base/metrics/histogram.h" -#include "base/metrics/histogram_samples.h" -#include "base/metrics/statistics_recorder.h" -#include "net/http/http_response_headers.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -using content::ResourceType; - namespace prerender { -class PrerenderUtilTest : public testing::Test { - public: - PrerenderUtilTest() { - } -}; - // Ensure that extracting a urlencoded URL in the url= query string component // works. -TEST_F(PrerenderUtilTest, ExtractURLInQueryStringTest) { +TEST(PrerenderUtilTest, ExtractURLInQueryStringTest) { GURL result; EXPECT_TRUE(MaybeGetQueryStringBasedAliasURL( - GURL("http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBcQFjAA&url=http%3A%2F%2Fwww.abercrombie.com%2Fwebapp%2Fwcs%2Fstores%2Fservlet%2FStoreLocator%3FcatalogId%3D%26storeId%3D10051%26langId%3D-1&rct=j&q=allinurl%3A%26&ei=KLyUTYGSEdTWiAKUmLCdCQ&usg=AFQjCNF8nJ2MpBFfr1ijO39_f22bcKyccw&sig2=2ymyGpO0unJwU1d4kdCUjQ"), + GURL( + "http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBcQFjAA&url=h" + "ttp%3A%2F%2Fwww.abercrombie.com%2Fwebapp%2Fwcs%2Fstores%2Fservlet%" + "2FStoreLocator%3FcatalogId%3D%26storeId%3D10051%26langId%3D-1&rct=" + "j&q=allinurl%3A%26&ei=KLyUTYGSEdTWiAKUmLCdCQ&usg=AFQjCNF8nJ2MpBFfr" + "1ijO39_f22bcKyccw&sig2=2ymyGpO0unJwU1d4kdCUjQ"), &result)); - ASSERT_EQ(GURL("http://www.abercrombie.com/webapp/wcs/stores/servlet/StoreLocator?catalogId=&storeId=10051&langId=-1").spec(), result.spec()); + ASSERT_EQ(GURL( + "http://www.abercrombie.com/webapp/wcs/stores/servlet/StoreLo" + "cator?catalogId=&storeId=10051&langId=-1").spec(), + result.spec()); EXPECT_FALSE(MaybeGetQueryStringBasedAliasURL( GURL("http://www.google.com/url?sadf=test&blah=blahblahblah"), &result)); EXPECT_FALSE(MaybeGetQueryStringBasedAliasURL( @@ -41,9 +37,15 @@ // Ensure that extracting an experiment in the lpe= query string component // works. -TEST_F(PrerenderUtilTest, ExtractExperimentInQueryStringTest) { - EXPECT_EQ(GetQueryStringBasedExperiment( - GURL("http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBcQFjAA&url=http%3A%2F%2Fwww.abercrombie.com%2Fwebapp%2Fwcs%2Fstores%2Fservlet%2FStoreLocator%3FcatalogId%3D%26storeId%3D10051%26langId%3D-1&rct=j&q=allinurl%3A%26&ei=KLyUTYGSEdTWiAKUmLCdCQ&usg=AFQjCNF8nJ2MpBFfr1ijO39_f22bcKyccw&sig2=2ymyGpO0unJwU1d4kdCUjQ&lpe=4&asdf=test")), 4); +TEST(PrerenderUtilTest, ExtractExperimentInQueryStringTest) { + EXPECT_EQ( + GetQueryStringBasedExperiment(GURL( + "http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBcQFjAA&url=h" + "ttp%3A%2F%2Fwww.abercrombie.com%2Fwebapp%2Fwcs%2Fstores%2Fservlet%" + "2FStoreLocator%3FcatalogId%3D%26storeId%3D10051%26langId%3D-1&rct=" + "j&q=allinurl%3A%26&ei=KLyUTYGSEdTWiAKUmLCdCQ&usg=AFQjCNF8nJ2MpBFfr" + "1ijO39_f22bcKyccw&sig2=2ymyGpO0unJwU1d4kdCUjQ&lpe=4&asdf=test")), + 4); EXPECT_EQ(GetQueryStringBasedExperiment( GURL("http://www.google.com/test.php?a=b")), kNoExperiment); EXPECT_EQ(GetQueryStringBasedExperiment( @@ -57,7 +59,7 @@ } // Ensure that we detect Google search result URLs correctly. -TEST_F(PrerenderUtilTest, DetectGoogleSearchREsultURLTest) { +TEST(PrerenderUtilTest, DetectGoogleSearchREsultURLTest) { EXPECT_TRUE(IsGoogleSearchResultURL(GURL("http://www.google.com/#asdf"))); EXPECT_TRUE(IsGoogleSearchResultURL(GURL("http://www.google.com/"))); EXPECT_TRUE(IsGoogleSearchResultURL(GURL("http://www.google.com/?a=b"))); @@ -80,149 +82,4 @@ EXPECT_FALSE(IsGoogleSearchResultURL(GURL("http://www.chromium.org/search"))); } -// Ensure that we count PageSpeed headers correctly. -TEST_F(PrerenderUtilTest, CountPageSpeedHeadersTest) { - base::StatisticsRecorder::Initialize(); - GURL url("http://google.com"); - std::string temp("HTTP/1.1 200 OK\n\n"); - std::replace(temp.begin(), temp.end(), '\n', '\0'); - scoped_refptr<net::HttpResponseHeaders> headers( - new net::HttpResponseHeaders(temp)); - - int num_responses = 0; - int num_mps = 0; - int num_ngx = 0; - int num_pss = 0; - int num_other = 0; - int num_bucket_1 = 0; // unrecognized format/value bucket - int num_bucket_30 = 0; // 1.2.24.1 bucket - int num_bucket_33 = 0; // 1.3.25.2 bucket - - scoped_ptr<base::HistogramSamples> server_samples; - scoped_ptr<base::HistogramSamples> version_samples; - - // No PageSpeed header. The VersionCounts histogram isn't created yet. - GatherPagespeedData(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); - base::HistogramBase* server_histogram = - base::StatisticsRecorder::FindHistogram( - "Prerender.PagespeedHeader.ServerCounts"); - ASSERT_TRUE(server_histogram != NULL); - ASSERT_TRUE(NULL == base::StatisticsRecorder::FindHistogram( - "Prerender.PagespeedHeader.VersionCounts")); - - server_samples = server_histogram->SnapshotSamples(); - EXPECT_EQ(++num_responses, server_samples->GetCount(0)); - EXPECT_EQ( num_mps, server_samples->GetCount(1)); - EXPECT_EQ( num_ngx, server_samples->GetCount(2)); - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ( num_other, server_samples->GetCount(4)); - - // X-Mod-Pagespeed header in expected format. VersionCounts now exists. - headers->AddHeader("X-Mod-Pagespeed: 1.2.24.1-2300"); - GatherPagespeedData(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); - base::HistogramBase* version_histogram = - base::StatisticsRecorder::FindHistogram( - "Prerender.PagespeedHeader.VersionCounts"); - ASSERT_TRUE(version_histogram != NULL); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ(++num_responses, server_samples->GetCount(0)); - EXPECT_EQ(++num_mps, server_samples->GetCount(1)); - EXPECT_EQ( num_ngx, server_samples->GetCount(2)); - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ( num_other, server_samples->GetCount(4)); - EXPECT_EQ( num_bucket_1, version_samples->GetCount(1)); - EXPECT_EQ(++num_bucket_30, version_samples->GetCount(30)); // +1 for #30 - EXPECT_EQ( num_bucket_33, version_samples->GetCount(33)); - headers->RemoveHeader("X-Mod-Pagespeed"); - - // X-Mod-Pagespeed header in unexpected format. - headers->AddHeader("X-Mod-Pagespeed: Powered By PageSpeed!"); - GatherPagespeedData(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ(++num_responses, server_samples->GetCount(0)); - EXPECT_EQ(++num_mps, server_samples->GetCount(1)); - EXPECT_EQ( num_ngx, server_samples->GetCount(2)); - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ( num_other, server_samples->GetCount(4)); - EXPECT_EQ(++num_bucket_1, version_samples->GetCount(1)); // +1 for 'huh?' - EXPECT_EQ( num_bucket_30, version_samples->GetCount(30)); - EXPECT_EQ( num_bucket_33, version_samples->GetCount(33)); - headers->RemoveHeader("X-Mod-Pagespeed"); - - // X-Page-Speed header in mod_pagespeed format (so ngx_pagespeed). - headers->AddHeader("X-Page-Speed: 1.3.25.2-2530"); - GatherPagespeedData(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ(++num_responses, server_samples->GetCount(0)); - EXPECT_EQ( num_mps, server_samples->GetCount(1)); - EXPECT_EQ(++num_ngx, server_samples->GetCount(2)); - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ( num_other, server_samples->GetCount(4)); - EXPECT_EQ( num_bucket_1, version_samples->GetCount(1)); - EXPECT_EQ( num_bucket_30, version_samples->GetCount(30)); - EXPECT_EQ(++num_bucket_33, version_samples->GetCount(33)); // +1 for #33 - headers->RemoveHeader("X-Page-Speed"); - - // X-Page-Speed header in PageSpeed Service format. - headers->AddHeader("X-Page-Speed: 97_4_bo"); - GatherPagespeedData(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ(++num_responses, server_samples->GetCount(0)); - EXPECT_EQ( num_mps, server_samples->GetCount(1)); // no change - EXPECT_EQ( num_ngx, server_samples->GetCount(2)); - EXPECT_EQ(++num_pss, server_samples->GetCount(3)); // +1 for PSS - EXPECT_EQ( num_other, server_samples->GetCount(4)); - EXPECT_EQ( num_bucket_1, version_samples->GetCount(1)); - EXPECT_EQ( num_bucket_30, version_samples->GetCount(30)); - EXPECT_EQ( num_bucket_33, version_samples->GetCount(33)); - headers->RemoveHeader("X-Page-Speed"); - - // X-Page-Speed header in an unrecognized format (IISpeed in this case). - headers->AddHeader("X-Page-Speed: 1.0PS1.2-20130615"); - GatherPagespeedData(content::RESOURCE_TYPE_MAIN_FRAME, url, headers.get()); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ(++num_responses, server_samples->GetCount(0)); - EXPECT_EQ( num_mps, server_samples->GetCount(1)); // no change - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ(++num_other, server_samples->GetCount(4)); // +1 for 'other' - EXPECT_EQ( num_bucket_1, version_samples->GetCount(1)); - EXPECT_EQ( num_bucket_30, version_samples->GetCount(30)); - EXPECT_EQ( num_bucket_33, version_samples->GetCount(33)); - - // Not a main frame => not counted at all. - GatherPagespeedData(content::RESOURCE_TYPE_SUB_FRAME, url, headers.get()); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ( num_responses, server_samples->GetCount(0)); - EXPECT_EQ( num_mps, server_samples->GetCount(1)); - EXPECT_EQ( num_ngx, server_samples->GetCount(2)); - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ( num_other, server_samples->GetCount(4)); - EXPECT_EQ( num_bucket_1, version_samples->GetCount(1)); - EXPECT_EQ( num_bucket_30, version_samples->GetCount(30)); - EXPECT_EQ( num_bucket_33, version_samples->GetCount(33)); - - // Not a http/https URL => not counted at all. - GURL data_url("data:image/png;base64,yadda yadda=="); - GatherPagespeedData( - content::RESOURCE_TYPE_MAIN_FRAME, data_url, headers.get()); - server_samples = server_histogram->SnapshotSamples(); - version_samples = version_histogram->SnapshotSamples(); - EXPECT_EQ( num_responses, server_samples->GetCount(0)); - EXPECT_EQ( num_mps, server_samples->GetCount(1)); - EXPECT_EQ( num_ngx, server_samples->GetCount(2)); - EXPECT_EQ( num_pss, server_samples->GetCount(3)); - EXPECT_EQ( num_other, server_samples->GetCount(4)); - EXPECT_EQ( num_bucket_1, version_samples->GetCount(1)); - EXPECT_EQ( num_bucket_30, version_samples->GetCount(30)); - EXPECT_EQ( num_bucket_33, version_samples->GetCount(33)); - - headers->RemoveHeader("X-Page-Speed"); -} - } // namespace prerender
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc index f427e87a..ad4f705 100644 --- a/chrome/browser/profiles/profile_info_cache.cc +++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -152,7 +152,8 @@ ProfileInfoCache::ProfileInfoCache(PrefService* prefs, const base::FilePath& user_data_dir) : prefs_(prefs), - user_data_dir_(user_data_dir) { + user_data_dir_(user_data_dir), + disable_avatar_download_for_testing_(false) { // Populate the cache DictionaryPrefUpdate update(prefs_, prefs::kProfileInfoCache); base::DictionaryValue* cache = update.Get(); @@ -181,7 +182,7 @@ // If needed, start downloading the high-res avatars and migrate any legacy // profile names. - if (switches::IsNewAvatarMenu()) + if (switches::IsNewAvatarMenu() && !disable_avatar_download_for_testing_) MigrateLegacyProfileNamesAndDownloadAvatars(); } @@ -220,7 +221,7 @@ sorted_keys_.insert(FindPositionForProfile(key, name), key); - if (switches::IsNewAvatarMenu()) + if (switches::IsNewAvatarMenu() && !disable_avatar_download_for_testing_) DownloadHighResAvatarIfNeeded(icon_index, profile_path); FOR_EACH_OBSERVER(ProfileInfoCacheObserver, @@ -318,7 +319,7 @@ } const gfx::Image& ProfileInfoCache::GetAvatarIconOfProfileAtIndex( - size_t index) const { + size_t index) { if (IsUsingGAIAPictureOfProfileAtIndex(index)) { const gfx::Image* image = GetGAIAPictureOfProfileAtIndex(index); if (image) @@ -544,7 +545,7 @@ base::FilePath profile_path = GetPathOfProfileAtIndex(index); - if (switches::IsNewAvatarMenu()) + if (switches::IsNewAvatarMenu() && !disable_avatar_download_for_testing_) DownloadHighResAvatarIfNeeded(icon_index, profile_path); FOR_EACH_OBSERVER(ProfileInfoCacheObserver, @@ -866,6 +867,7 @@ #if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS) return; #endif + DCHECK(!disable_avatar_download_for_testing_); const base::FilePath& file_path = profiles::GetPathOfHighResAvatarAtIndex(icon_index); @@ -1065,6 +1067,10 @@ return cached_avatar_images_[key]; } + // Don't download the image if downloading is disabled for tests. + if (disable_avatar_download_for_testing_) + return NULL; + // If the picture is already being loaded then don't try loading it again. if (cached_avatar_images_loading_[key]) return NULL;
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h index 7b005fc..7b935f8 100644 --- a/chrome/browser/profiles/profile_info_cache.h +++ b/chrome/browser/profiles/profile_info_cache.h
@@ -62,7 +62,7 @@ base::FilePath GetPathOfProfileAtIndex(size_t index) const override; base::Time GetProfileActiveTimeAtIndex(size_t index) const override; base::string16 GetUserNameOfProfileAtIndex(size_t index) const override; - const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) const override; + const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) override; std::string GetLocalAuthCredentialsOfProfileAtIndex( size_t index) const override; // Note that a return value of false could mean an error in collection or @@ -148,6 +148,11 @@ void AddObserver(ProfileInfoCacheObserver* obs); void RemoveObserver(ProfileInfoCacheObserver* obs); + void set_disable_avatar_download_for_testing( + bool disable_avatar_download_for_testing) { + disable_avatar_download_for_testing_ = disable_avatar_download_for_testing; + } + private: FRIEND_TEST_ALL_PREFIXES(ProfileInfoCacheTest, DownloadHighResAvatarTest); @@ -224,6 +229,10 @@ std::map<std::string, ProfileAvatarDownloader*> avatar_images_downloads_in_progress_; + // Determines of the ProfileAvatarDownloader should be created and executed + // or not. Only set to true for tests. + bool disable_avatar_download_for_testing_; + DISALLOW_COPY_AND_ASSIGN(ProfileInfoCache); };
diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc index feb143a..1f66b58c 100644 --- a/chrome/browser/profiles/profile_info_cache_unittest.cc +++ b/chrome/browser/profiles/profile_info_cache_unittest.cc
@@ -546,27 +546,37 @@ switches::EnableNewAvatarMenuForTesting( base::CommandLine::ForCurrentProcess()); - EXPECT_EQ(0U, GetCache()->GetNumberOfProfiles()); + // The TestingProfileManager's ProfileInfoCache doesn't download avatars. + ProfileInfoCache profile_info_cache(g_browser_process->local_state(), + testing_profile_manager_.profile_manager()->user_data_dir()); + + // // Make sure there are no avatars already on disk. + const size_t kIconIndex = 0; + base::FilePath icon_path = + profiles::GetPathOfHighResAvatarAtIndex(kIconIndex); + EXPECT_FALSE(base::PathExists(icon_path)); + + EXPECT_EQ(0U, profile_info_cache.GetNumberOfProfiles()); base::FilePath path_1 = GetProfilePath("path_1"); - GetCache()->AddProfileToCache(path_1, ASCIIToUTF16("name_1"), - base::string16(), 0, std::string()); - EXPECT_EQ(1U, GetCache()->GetNumberOfProfiles()); + profile_info_cache.AddProfileToCache(path_1, ASCIIToUTF16("name_1"), + base::string16(), kIconIndex, std::string()); + EXPECT_EQ(1U, profile_info_cache.GetNumberOfProfiles()); base::RunLoop().RunUntilIdle(); // We haven't downloaded any high-res avatars yet. - EXPECT_EQ(0U, GetCache()->cached_avatar_images_.size()); + EXPECT_EQ(0U, profile_info_cache.cached_avatar_images_.size()); // After adding a new profile, the download of high-res avatar will be // triggered if the flag kNewAvatarMenu has been set. But the downloader // won't ever call OnFetchComplete in the test. - EXPECT_EQ(1U, GetCache()->avatar_images_downloads_in_progress_.size()); + EXPECT_EQ(1U, profile_info_cache.avatar_images_downloads_in_progress_.size()); - EXPECT_FALSE(GetCache()->GetHighResAvatarOfProfileAtIndex(0)); + EXPECT_FALSE(profile_info_cache.GetHighResAvatarOfProfileAtIndex(0)); // Simulate downloading a high-res avatar. - const size_t kIconIndex = 0; ProfileAvatarDownloader avatar_downloader( - kIconIndex, GetCache()->GetPathOfProfileAtIndex(0), GetCache()); + kIconIndex, profile_info_cache.GetPathOfProfileAtIndex(0), + &profile_info_cache); // Put a real bitmap into "bitmap". 2x2 bitmap of green 32 bit pixels. SkBitmap bitmap; @@ -577,23 +587,21 @@ GURL("http://www.google.com/avatar.png"), &bitmap); // Now the download should not be in progress anymore. - EXPECT_EQ(0U, GetCache()->avatar_images_downloads_in_progress_.size()); + EXPECT_EQ(0U, profile_info_cache.avatar_images_downloads_in_progress_.size()); std::string file_name = profiles::GetDefaultAvatarIconFileNameAtIndex(kIconIndex); // The file should have been cached and saved. - EXPECT_EQ(1U, GetCache()->cached_avatar_images_.size()); - EXPECT_TRUE(GetCache()->GetHighResAvatarOfProfileAtIndex(0)); - EXPECT_EQ(GetCache()->cached_avatar_images_[file_name], - GetCache()->GetHighResAvatarOfProfileAtIndex(0)); + EXPECT_EQ(1U, profile_info_cache.cached_avatar_images_.size()); + EXPECT_TRUE(profile_info_cache.GetHighResAvatarOfProfileAtIndex(0)); + EXPECT_EQ(profile_info_cache.cached_avatar_images_[file_name], + profile_info_cache.GetHighResAvatarOfProfileAtIndex(0)); // Make sure everything has completed, and the file has been written to disk. base::RunLoop().RunUntilIdle(); // Clean up. - base::FilePath icon_path = - profiles::GetPathOfHighResAvatarAtIndex(kIconIndex); EXPECT_NE(std::string::npos, icon_path.MaybeAsASCII().find(file_name)); EXPECT_TRUE(base::PathExists(icon_path)); EXPECT_TRUE(base::DeleteFile(icon_path, true));
diff --git a/chrome/browser/profiles/profile_info_interface.h b/chrome/browser/profiles/profile_info_interface.h index 555f154..a314cc9 100644 --- a/chrome/browser/profiles/profile_info_interface.h +++ b/chrome/browser/profiles/profile_info_interface.h
@@ -37,8 +37,7 @@ virtual base::string16 GetUserNameOfProfileAtIndex(size_t index) const = 0; - virtual const gfx::Image& GetAvatarIconOfProfileAtIndex( - size_t index) const = 0; + virtual const gfx::Image& GetAvatarIconOfProfileAtIndex(size_t index) = 0; virtual std::string GetLocalAuthCredentialsOfProfileAtIndex( size_t index) const = 0;
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 88ea1699..bfa527c 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1043,11 +1043,14 @@ command_line, quick_check_enabled_.GetValue())); transport_security_state_.reset(new net::TransportSecurityState()); + base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); transport_security_persister_.reset( new net::TransportSecurityPersister( transport_security_state_.get(), profile_params_->path, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), + pool->GetSequencedTaskRunnerWithShutdownBehavior( + pool->GetSequenceToken(), + base::SequencedWorkerPool::BLOCK_SHUTDOWN), IsOffTheRecord())); // Take ownership over these parameters.
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc index f8f35851..e02816c 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/component_updater/component_updater_resource_throttle.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_resource_throttle.h" +#include "chrome/browser/mod_pagespeed/mod_pagespeed_metrics.h" #include "chrome/browser/net/resource_prefetch_predictor_observer.h" #include "chrome/browser/plugins/plugin_prefs.h" #include "chrome/browser/prefetch/prefetch.h" @@ -688,7 +689,8 @@ response_headers->RemoveHeader("x-frame-options"); } - prerender::URLRequestResponseStarted(request); + mod_pagespeed::RecordMetrics(info->GetResourceType(), request->url(), + request->response_headers()); } void ChromeResourceDispatcherHostDelegate::OnRequestRedirected(
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/console_tts.js b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/console_tts.js index 00abb033a..306ab27 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/console_tts.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/console_tts.js
@@ -42,14 +42,6 @@ } logStr += ' "' + textString + '"'; window['console']['log'](logStr); - - if (properties && properties['startCallback'] != undefined) { - window.console.log(' using startCallback'); - } - - if (properties && properties['endCallback'] != undefined) { - window.console.log(' using endCallback'); - } } return this; };
diff --git a/chrome/browser/resources/chromeos/login/gaia_whiteist_error.js b/chrome/browser/resources/chromeos/login/gaia_whiteist_error.js new file mode 100644 index 0000000..eed9092 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/gaia_whiteist_error.js
@@ -0,0 +1,20 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +Polymer('gaia-whitelist-error', (function() { + // The help topic regarding user not being in the whitelist. + /** @const */ var HELP_CANT_ACCESS_ACCOUNT = 188036; + + return { + enterpriseManaged: false, + + onLearnMoreClicked: function() { + chrome.send('launchHelpApp', [HELP_CANT_ACCESS_ACCOUNT]); + }, + + tryAgainButtonClicked: function() { + $('gaia-signin').showWhitelistCheckFailedError(false); + } + }; +})());
diff --git a/chrome/browser/resources/chromeos/login/gaia_whitelist_error.html b/chrome/browser/resources/chromeos/login/gaia_whitelist_error.html new file mode 100644 index 0000000..b8c2a3cf --- /dev/null +++ b/chrome/browser/resources/chromeos/login/gaia_whitelist_error.html
@@ -0,0 +1,72 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/core-icons/core-icons.html"> + +<polymer-element name="gaia-whitelist-error" attributes="errorMsg + enterpriseErrorMsg tryAgainBtn learnMoreBtn"> + <template> + <style> + #container { + padding: 40px; + } + + #icon-container { + margin-bottom: 14px; + } + + core-icon { + color: #fbc02d; + height: 28px; + width: 28px; + } + + #text-container { + color: grey; + line-height: 130%; + text-align: center; + width: 240px; + } + + #controls-container { + width: 100%; + } + + .learn-more-button { + color: rgb(66, 133, 244); + text-transform: none; + } + + .try-again-button { + background-color: rgb(66, 133, 244); + color: rgb(255, 255, 255); + width: 126px; + } + </style> + <div id="container" vertical layout center fit> + <div flex layout center-justified vertical> + <div id="icon-container" vertical layout center> + <core-icon icon="warning"></core-icon> + </div> + <div id="text-container"> + <div id="error-msg" hidden?="{{enterpriseManaged}}"> + {{errorMsg}} + </div> + <div id="enterprise-error-msg" hidden?="{{!enterpriseManaged}}"> + {{enterpriseErrorMsg}} + </div> + </div> + </div> + <div id="controls-container" horizontal layout justified + center> + <paper-button class="learn-more-button" + on-tap={{onLearnMoreClicked}}> + {{learnMoreBtn}} + </paper-button> + <paper-button class="try-again-button" raised + on-tap="{{tryAgainButtonClicked}}"> + {{tryAgainBtn}} + </paper-button> + </div> + </div> + </template> +</polymer-element> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/login.html b/chrome/browser/resources/chromeos/login/login.html index db0aa76a4f..0bbe68e2 100644 --- a/chrome/browser/resources/chromeos/login/login.html +++ b/chrome/browser/resources/chromeos/login/login.html
@@ -9,6 +9,7 @@ <title i18n-content="title"></title> <include src="login_resources.html"> <include src="throbber_notice.html"> +<include src="gaia_whitelist_error.html"> <script src="chrome://oobe/login.js"></script> <script src="chrome://oobe/gaia_auth_host.js"></script> </head> @@ -16,4 +17,4 @@ <include src="screen_container.html"> <script src="chrome://resources/js/i18n_template2.js"></script> </body> -</html> +</html> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/login.js b/chrome/browser/resources/chromeos/login/login.js index 393130e..7f9ac0a0 100644 --- a/chrome/browser/resources/chromeos/login/login.js +++ b/chrome/browser/resources/chromeos/login/login.js
@@ -7,6 +7,7 @@ */ <include src="login_common.js"> +<include src="gaia_whiteist_error.js"> cr.define('cr.ui.Oobe', function() { return {
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css index f8491e8b..3e4894c5 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
@@ -242,3 +242,29 @@ #saml-notice-message { margin: 0 auto; } + +#gaia-whitelist-error { + bottom: 0; + display: none; + left: 0; + position: absolute; + right: 0; + top: 0; +} + +.new-gaia-flow #gaia-whitelist-error { + display: block; + visibility: hidden; +} + +.new-gaia-flow .whitelist-error #gaia-whitelist-error { + visibility: visible; +} + +.new-gaia-flow #gaia-signin.whitelist-error .step-contents { + visibility: hidden; +} + +.new-gaia-flow #gaia-signin.whitelist-error .step-loading { + visibility: hidden; +} \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html index a665ee0..93f80843 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
@@ -31,6 +31,13 @@ <div class="throbber"></div> <throbber-notice i18n-values="text:gaiaLoadingNewGaia"></throbber-notice> </div> + <gaia-whitelist-error + i18n-values="errorMsg:whitelistErrorConsumer; + enterpriseErrorMsg:whitelistErrorEnterprise; + tryAgainBtn:tryAgainButton; + learnMoreBtn:learnMoreButton" + id="gaia-whitelist-error"> + </gaia-whitelist-error> <div id="enterprise-info-container" hidden> <include src="enterprise_info.html"> </div>
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index db9ff4f..9fc14fad 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -23,7 +23,8 @@ 'doReload', 'onWebviewError', 'onFrameError', - 'updateCancelButtonState' + 'updateCancelButtonState', + 'showWhitelistCheckFailedError' ], /** @@ -750,6 +751,7 @@ $('pod-row').loadLastWallpaper(); Oobe.showScreen({id: SCREEN_ACCOUNT_PICKER}); + this.classList.remove('whitelist-error'); Oobe.resetSigninUI(true); }, @@ -773,5 +775,24 @@ onWebviewError: function(data) { chrome.send('webviewLoadAborted', [data.error]); }, + + /** + * Show/Hide error when user is not in whitelist. When UI is hidden + * GAIA is reloaded. + * @param {boolean} show Show/hide error UI. + * @param {!Object} opt_data Optional additional information. + */ + showWhitelistCheckFailedError: function(show, opt_data) { + if (opt_data) { + $('gaia-whitelist-error').enterpriseManaged = + opt_data.enterpriseManaged; + } + + this.classList.toggle('whitelist-error', show); + this.loading = !show; + + if (!show) + Oobe.showSigninUI(); + }, }; });
diff --git a/chrome/browser/resources/gaia_auth_host/saml_handler.js b/chrome/browser/resources/gaia_auth_host/saml_handler.js index 20418d6..b41fad8 100644 --- a/chrome/browser/resources/gaia_auth_host/saml_handler.js +++ b/chrome/browser/resources/gaia_auth_host/saml_handler.js
@@ -266,6 +266,12 @@ return; } + // Skip for none http/https url. + if (e.url.indexOf('https://') != 0 && + e.url.indexOf('http://') != 0) { + return; + } + this.isSamlPage_ = this.pendingIsSamlPage_; this.injectJs_(); },
diff --git a/chrome/browser/resources/options/browser_options_profile_list.js b/chrome/browser/resources/options/browser_options_profile_list.js index 81a4181..96adf2f 100644 --- a/chrome/browser/resources/options/browser_options_profile_list.js +++ b/chrome/browser/resources/options/browser_options_profile_list.js
@@ -51,6 +51,7 @@ var iconEl = this.ownerDocument.createElement('img'); iconEl.className = 'profile-img'; iconEl.style.content = getProfileAvatarIcon(profileInfo.iconURL); + iconEl.alt = ''; containerEl.appendChild(iconEl); var nameEl = this.ownerDocument.createElement('div');
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc index 74b1b67..a6957f01 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win.cc
@@ -129,6 +129,7 @@ const wchar_t* const modules_to_verify[], size_t num_modules_to_verify, ClientIncidentReport_EnvironmentData_Process* process) { +#if !defined(_WIN64) for (size_t i = 0; i < num_modules_to_verify; ++i) { scoped_ptr<ClientIncidentReport_EnvironmentData_Process_ModuleState> module_state( @@ -191,6 +192,7 @@ } process->mutable_module_state()->AddAllocated(module_state.release()); } +#endif // _WIN64 } void CollectPlatformProcessData(
diff --git a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc index 9be80141..9a6f476 100644 --- a/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/environment_data_collection_win_unittest.cc
@@ -169,6 +169,7 @@ EXPECT_EQ(path_expected, process_report_path); } +#if !defined(_WIN64) TEST(SafeBrowsingEnvironmentDataCollectionWinTest, VerifyLoadedModules) { // Load the test modules. std::vector<base::ScopedNativeLibrary> test_dlls(kTestDllNamesCount); @@ -218,5 +219,6 @@ EXPECT_EQ(std::string(kTestExportName), process_report.module_state(0).modified_export(0)); } +#endif // _WIN64 } // namespace safe_browsing
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index 80fe3c2..a7f8ea9 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -22,9 +22,8 @@ #include "chrome/common/pref_names.h" #include "chromeos/login/user_names.h" #include "components/pref_registry/pref_registry_syncable.h" -#include "components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h" -#include "components/proximity_auth/cryptauth/cryptauth_client.h" -#include "components/proximity_auth/cryptauth/cryptauth_client_factory.h" +#include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" +#include "components/proximity_auth/cryptauth/cryptauth_client_impl.h" #include "components/proximity_auth/switches.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" @@ -223,7 +222,7 @@ SetTurnOffFlowStatus(PENDING); - proximity_auth::CryptAuthClientFactory factory( + proximity_auth::CryptAuthClientFactoryImpl factory( ProfileOAuth2TokenServiceFactory::GetForProfile(profile()), SigninManagerFactory::GetForProfile(profile()) ->GetAuthenticatedAccountId(),
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc index 028aa8b..63211fe 100644 --- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc +++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
@@ -15,7 +15,7 @@ const char kFamilyApiUrl[] = "https://www.googleapis.com/kidsmanagement/v1/"; const char kGetFamilyProfileApiSuffix[] = "families/mine?alt=json"; const char kGetFamilyMembersApiSuffix[] = "families/mine/members?alt=json"; -const char kScope[] = "https://www.googleapis.com/auth/kid.family"; +const char kScope[] = "https://www.googleapis.com/auth/kid.family.readonly"; const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; const int kNumRetries = 1;
diff --git a/chrome/browser/supervised_user/supervised_user_resource_throttle.cc b/chrome/browser/supervised_user/supervised_user_resource_throttle.cc index 1224a78..55b329f 100644 --- a/chrome/browser/supervised_user/supervised_user_resource_throttle.cc +++ b/chrome/browser/supervised_user/supervised_user_resource_throttle.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/supervised_user/supervised_user_resource_throttle.h" #include "base/bind.h" -#include "base/metrics/histogram.h" +#include "base/metrics/sparse_histogram.h" #include "chrome/browser/supervised_user/supervised_user_interstitial.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" @@ -28,14 +28,16 @@ FILTERING_BEHAVIOR_ALLOW_UNCERTAIN, FILTERING_BEHAVIOR_BLOCK_BLACKLIST, FILTERING_BEHAVIOR_BLOCK_SAFESITES, - FILTERING_BEHAVIOR_MAX = FILTERING_BEHAVIOR_BLOCK_SAFESITES + FILTERING_BEHAVIOR_BLOCK_MANUAL, + FILTERING_BEHAVIOR_BLOCK_DEFAULT, + FILTERING_BEHAVIOR_MAX = FILTERING_BEHAVIOR_BLOCK_DEFAULT }; const int kHistogramFilteringBehaviorSpacing = 100; const int kHistogramPageTransitionMaxKnownValue = static_cast<int>(ui::PAGE_TRANSITION_KEYWORD_GENERATED); const int kHistogramPageTransitionFallbackValue = kHistogramFilteringBehaviorSpacing - 1; -const int kHistogramMax = 500; +const int kHistogramMax = 700; static_assert(kHistogramPageTransitionMaxKnownValue < kHistogramPageTransitionFallbackValue, @@ -54,12 +56,17 @@ return uncertain ? FILTERING_BEHAVIOR_ALLOW_UNCERTAIN : FILTERING_BEHAVIOR_ALLOW; case SupervisedUserURLFilter::BLOCK: - if (reason == SupervisedUserURLFilter::BLACKLIST) - return FILTERING_BEHAVIOR_BLOCK_BLACKLIST; - else if (reason == SupervisedUserURLFilter::ASYNC_CHECKER) - return FILTERING_BEHAVIOR_BLOCK_SAFESITES; - // Fall through. - default: + switch (reason) { + case SupervisedUserURLFilter::BLACKLIST: + return FILTERING_BEHAVIOR_BLOCK_BLACKLIST; + case SupervisedUserURLFilter::ASYNC_CHECKER: + return FILTERING_BEHAVIOR_BLOCK_SAFESITES; + case SupervisedUserURLFilter::MANUAL: + return FILTERING_BEHAVIOR_BLOCK_MANUAL; + case SupervisedUserURLFilter::DEFAULT: + return FILTERING_BEHAVIOR_BLOCK_DEFAULT; + } + case SupervisedUserURLFilter::INVALID: NOTREACHED(); } return 0; @@ -75,19 +82,23 @@ } void RecordFilterResultEvent( + bool safesites_histogram, SupervisedUserURLFilter::FilteringBehavior behavior, SupervisedUserURLFilter::FilteringBehaviorReason reason, bool uncertain, ui::PageTransition transition_type) { - DCHECK(reason == SupervisedUserURLFilter::ASYNC_CHECKER || - reason == SupervisedUserURLFilter::BLACKLIST); int value = GetHistogramValueForFilteringBehavior(behavior, reason, uncertain) * kHistogramFilteringBehaviorSpacing + GetHistogramValueForTransitionType(transition_type); DCHECK_LT(value, kHistogramMax); - UMA_HISTOGRAM_ENUMERATION("ManagedUsers.SafetyFilter", - value, kHistogramMax); + // Note: We can't pass in the histogram name as a parameter to this function + // because of how the macro works (look up the histogram on the first + // invocation and cache it in a static variable). + if (safesites_histogram) + UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.SafetyFilter", value); + else + UMA_HISTOGRAM_SPARSE_SLOWLY("ManagedUsers.FilteringResult", value); } } // namespace @@ -100,7 +111,7 @@ is_main_frame_(is_main_frame), url_filter_(url_filter), deferred_(false), - behavior_(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE), + behavior_(SupervisedUserURLFilter::INVALID), weak_ptr_factory_(this) {} SupervisedUserResourceThrottle::~SupervisedUserResourceThrottle() {} @@ -113,18 +124,17 @@ return; deferred_ = false; - DCHECK_EQ(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE, behavior_); + DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( url, base::Bind(&SupervisedUserResourceThrottle::OnCheckDone, weak_ptr_factory_.GetWeakPtr(), url)); - DCHECK_EQ(got_result, - (behavior_ != SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE)); + DCHECK_EQ(got_result, behavior_ != SupervisedUserURLFilter::INVALID); // If we got a "not blocked" result synchronously, don't defer. *defer = deferred_ = !got_result || (behavior_ == SupervisedUserURLFilter::BLOCK); if (got_result) - behavior_ = SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE; + behavior_ = SupervisedUserURLFilter::INVALID; } void SupervisedUserResourceThrottle::ShowInterstitial( @@ -159,19 +169,22 @@ SupervisedUserURLFilter::FilteringBehavior behavior, SupervisedUserURLFilter::FilteringBehaviorReason reason, bool uncertain) { - DCHECK_EQ(SupervisedUserURLFilter::HISTOGRAM_BOUNDING_VALUE, behavior_); + DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); // If we got a result synchronously, pass it back to ShowInterstitialIfNeeded. if (!deferred_) behavior_ = behavior; - // If both the static blacklist and SafeSites are enabled, record UMA events. + ui::PageTransition transition = + content::ResourceRequestInfo::ForRequest(request_)->GetPageTransition(); + + RecordFilterResultEvent(false, behavior, reason, uncertain, transition); + + // If both the static blacklist and the async checker are enabled, also record + // SafeSites-only UMA events. if (url_filter_->HasBlacklist() && url_filter_->HasAsyncURLChecker() && (reason == SupervisedUserURLFilter::ASYNC_CHECKER || reason == SupervisedUserURLFilter::BLACKLIST)) { - const content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request_); - RecordFilterResultEvent(behavior, reason, uncertain, - info->GetPageTransition()); + RecordFilterResultEvent(true, behavior, reason, uncertain, transition); } if (behavior == SupervisedUserURLFilter::BLOCK)
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc index 5305ee2..b08be12 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter.cc +++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -10,7 +10,6 @@ #include "base/containers/hash_tables.h" #include "base/files/file_path.h" #include "base/json/json_file_value_serializer.h" -#include "base/metrics/histogram.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -417,16 +416,12 @@ const std::map<std::string, bool>* host_map) { DCHECK(CalledOnValidThread()); host_map_ = *host_map; - UMA_HISTOGRAM_CUSTOM_COUNTS("ManagedMode.ManualHostsEntries", - host_map->size(), 1, 1000, 50); } void SupervisedUserURLFilter::SetManualURLs( const std::map<GURL, bool>* url_map) { DCHECK(CalledOnValidThread()); url_map_ = *url_map; - UMA_HISTOGRAM_CUSTOM_COUNTS("ManagedMode.ManualURLsEntries", - url_map->size(), 1, 1000, 50); } void SupervisedUserURLFilter::InitAsyncURLChecker(
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.h b/chrome/browser/supervised_user/supervised_user_url_filter.h index 3637c17..7eaa4be 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter.h +++ b/chrome/browser/supervised_user/supervised_user_url_filter.h
@@ -48,7 +48,7 @@ ALLOW, WARN, BLOCK, - HISTOGRAM_BOUNDING_VALUE + INVALID }; enum FilteringBehaviorReason { DEFAULT,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 8075c41..6d4f898 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -11,7 +11,7 @@ "scope", [ "../../chrome_browser_ui.gypi" ]) -static_library("ui") { +source_set("ui") { output_name = "browser_ui" sources = []
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc index 8297968..4607df8c 100644 --- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc +++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
@@ -33,10 +33,9 @@ DCHECK(view_android); java_object_.Reset(Java_AutofillPopupBridge_create( - env, - reinterpret_cast<intptr_t>(this), + env, reinterpret_cast<intptr_t>(this), view_android->GetWindowAndroid()->GetJavaObject().obj(), - view_android->GetJavaObject().obj())); + view_android->GetViewAndroidDelegate().obj())); UpdateBoundsAndRedrawPopup(); }
diff --git a/chrome/browser/ui/android/autofill/password_generation_popup_view_android.cc b/chrome/browser/ui/android/autofill/password_generation_popup_view_android.cc index 57ef6574..f09cda2f 100644 --- a/chrome/browser/ui/android/autofill/password_generation_popup_view_android.cc +++ b/chrome/browser/ui/android/autofill/password_generation_popup_view_android.cc
@@ -58,10 +58,9 @@ DCHECK(view_android); java_object_.Reset(Java_PasswordGenerationPopupBridge_create( - env, - reinterpret_cast<intptr_t>(this), + env, reinterpret_cast<intptr_t>(this), view_android->GetWindowAndroid()->GetJavaObject().obj(), - view_android->GetJavaObject().obj())); + view_android->GetViewAndroidDelegate().obj())); UpdateBoundsAndRedrawPopup(); }
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm index d65553a..f337879 100644 --- a/chrome/browser/ui/app_list/app_list_service_mac.mm +++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -86,20 +86,21 @@ // Distance towards the screen edge that the app list moves from when showing. const CGFloat kDistanceMovedOnShow = 20; -web_app::ShortcutInfo GetAppListShortcutInfo( +scoped_ptr<web_app::ShortcutInfo> GetAppListShortcutInfo( const base::FilePath& profile_path) { - web_app::ShortcutInfo shortcut_info; + scoped_ptr<web_app::ShortcutInfo> shortcut_info(new web_app::ShortcutInfo); chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); if (channel == chrome::VersionInfo::CHANNEL_CANARY) { - shortcut_info.title = + shortcut_info->title = l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME_CANARY); } else { - shortcut_info.title = l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME); + shortcut_info->title = + l10n_util::GetStringUTF16(IDS_APP_LIST_SHORTCUT_NAME); } - shortcut_info.extension_id = app_mode::kAppListModeId; - shortcut_info.description = shortcut_info.title; - shortcut_info.profile_path = profile_path; + shortcut_info->extension_id = app_mode::kAppListModeId; + shortcut_info->description = shortcut_info->title; + shortcut_info->profile_path = profile_path; return shortcut_info; } @@ -107,32 +108,32 @@ void CreateAppListShim(const base::FilePath& profile_path) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); WebApplicationInfo web_app_info; - web_app::ShortcutInfo shortcut_info = + scoped_ptr<web_app::ShortcutInfo> shortcut_info = GetAppListShortcutInfo(profile_path); ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); if (channel == chrome::VersionInfo::CHANNEL_CANARY) { #if defined(GOOGLE_CHROME_BUILD) - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_16)); - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_32)); - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_128)); - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_CANARY_256)); #else NOTREACHED(); #endif } else { - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_16)); - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_32)); - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_128)); - shortcut_info.favicon.Add( + shortcut_info->favicon.Add( *resource_bundle.GetImageSkiaNamed(IDR_APP_LIST_256)); } @@ -148,7 +149,7 @@ if (installed_version == 0) shortcut_locations.in_quick_launch_bar = true; - web_app::CreateNonAppShortcut(shortcut_locations, shortcut_info); + web_app::CreateNonAppShortcut(shortcut_locations, shortcut_info.Pass()); local_state->SetInteger(prefs::kAppLauncherShortcutVersion, kShortcutVersion);
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index b2fae69..dca8caf 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -94,11 +94,11 @@ void CreateShortcutInWebAppDir( const base::FilePath& app_data_dir, base::Callback<void(const base::FilePath&)> callback, - const web_app::ShortcutInfo& info) { + scoped_ptr<web_app::ShortcutInfo> info) { content::BrowserThread::PostTaskAndReplyWithResult( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(web_app::CreateShortcutInWebAppDir, app_data_dir, info), + content::BrowserThread::FILE, FROM_HERE, + base::Bind(web_app::CreateShortcutInWebAppDir, app_data_dir, + base::Passed(&info)), callback); } #endif
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index 8899852..612c61f81 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -22,8 +22,13 @@ #include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) +#include "base/prefs/pref_service.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/display/display_configuration_observer.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #endif @@ -88,6 +93,20 @@ return false; } +bool ChromeShellDelegate::IsForceMaximizeOnFirstRun() const { +#if defined(OS_CHROMEOS) + const user_manager::User* const user = + user_manager::UserManager::Get()->GetActiveUser(); + if (user) { + return chromeos::ProfileHelper::Get() + ->GetProfileByUser(user) + ->GetPrefs() + ->GetBoolean(prefs::kForceMaximizeOnFirstRun); + } +#endif + return false; +} + void ChromeShellDelegate::Exit() { chrome::AttemptUserExit(); }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h index fc9bc1c..a467a6e 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.h +++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -52,6 +52,7 @@ bool IsIncognitoAllowed() const override; bool IsRunningInForcedAppMode() const override; bool IsMultiAccountEnabled() const override; + bool IsForceMaximizeOnFirstRun() const override; void PreInit() override; void PreShutdown() override; void Exit() override;
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_sync_promo_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_sync_promo_controller_unittest.mm index 90160c1..2a82c2f 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_sync_promo_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_sync_promo_controller_unittest.mm
@@ -14,6 +14,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/browser_with_test_window_test.h" +#include "components/signin/core/common/profile_management_switches.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -21,6 +22,8 @@ class BookmarkSyncPromoControllerTest : public BrowserWithTestWindowTest { public: void SetUp() override { + switches::DisableNewAvatarMenuForTesting( + base::CommandLine::ForCurrentProcess()); BrowserWithTestWindowTest::SetUp(); ASSERT_TRUE(profile()); // Adds TestExtensionSystem, since signin uses the gaia auth extension.
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_icon_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/avatar_icon_controller_unittest.mm index 026e42d..3f29a4c 100644 --- a/chrome/browser/ui/cocoa/profiles/avatar_icon_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/profiles/avatar_icon_controller_unittest.mm
@@ -4,6 +4,7 @@ #import "chrome/browser/ui/cocoa/profiles/avatar_icon_controller.h" +#include "base/command_line.h" #include "base/mac/scoped_nsobject.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" @@ -22,10 +23,13 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/testing_profile.h" #include "components/bookmarks/test/bookmark_test_helpers.h" +#include "components/signin/core/common/profile_management_switches.h" class AvatarIconControllerTest : public CocoaProfileTest { public: void SetUp() override { + switches::DisableNewAvatarMenuForTesting( + base::CommandLine::ForCurrentProcess()); CocoaProfileTest::SetUp(); ASSERT_TRUE(browser());
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm index d48823787..d357b89 100644 --- a/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm
@@ -4,6 +4,7 @@ #import "chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller.h" +#include "base/command_line.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_pump_mac.h" @@ -15,6 +16,7 @@ #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "components/signin/core/common/profile_management_switches.h" #include "testing/gtest_mac.h" #import "ui/base/cocoa/controls/hyperlink_button_cell.h" #include "ui/events/test/cocoa_test_event_utils.h" @@ -26,6 +28,9 @@ } void SetUp() override { + switches::DisableNewAvatarMenuForTesting( + base::CommandLine::ForCurrentProcess()); + CocoaTest::SetUp(); ASSERT_TRUE(manager_.SetUp()); @@ -78,7 +83,7 @@ NSView* contents = [[controller() window] contentView]; EXPECT_EQ(4U, [[contents subviews] count]); - // Loop over the itmes and match the viewController views to subviews. + // Loop over the items and match the viewController views to subviews. NSMutableArray* subviews = [NSMutableArray arrayWithArray:[contents subviews]]; for (AvatarMenuItemController* viewController in [controller() items]) {
diff --git a/chrome/browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm index e2acb1c..ee9bd7b 100644 --- a/chrome/browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/profiles/profile_menu_controller_unittest.mm
@@ -80,12 +80,12 @@ TEST_F(ProfileMenuControllerTest, InitializeMenu) { NSMenu* menu = [controller() menu]; - // <sep>, Edit, <sep>, New. - ASSERT_EQ(4, [menu numberOfItems]); + // Profile, <sep>, Edit, <sep>, New. + ASSERT_EQ(5, [menu numberOfItems]); TestBottomItems(); - EXPECT_TRUE([menu_item() isHidden]); + EXPECT_FALSE([menu_item() isHidden]); } TEST_F(ProfileMenuControllerTest, CreateItemWithTitle) { @@ -100,9 +100,9 @@ TEST_F(ProfileMenuControllerTest, RebuildMenu) { NSMenu* menu = [controller() menu]; - EXPECT_EQ(4, [menu numberOfItems]); + EXPECT_EQ(5, [menu numberOfItems]); - EXPECT_TRUE([menu_item() isHidden]); + EXPECT_FALSE([menu_item() isHidden]); // Create some more profiles on the manager. TestingProfileManager* manager = testing_profile_manager(); @@ -130,12 +130,12 @@ base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]); ASSERT_EQ(0, [menu numberOfItems]); - // With only one profile, insertItems should be a no-op. + // Even with one profile items can still be inserted. BOOL result = [controller() insertItemsIntoMenu:menu atOffset:0 fromDock:NO]; - EXPECT_FALSE(result); - EXPECT_EQ(0, [menu numberOfItems]); + EXPECT_TRUE(result); + EXPECT_EQ(1, [menu numberOfItems]); [menu removeAllItems]; // Same for use in building the dock menu.
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm index c13b3621..8dde6a25 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -1554,10 +1554,8 @@ NSInteger index = [self indexFromModelIndex:modelIndex]; TabController* tabController = [tabArray_ objectAtIndex:index]; - FaviconTabHelper* favicon_tab_helper = - FaviconTabHelper::FromWebContents(contents); bool oldHasIcon = [tabController iconView] != nil; - bool newHasIcon = favicon_tab_helper->ShouldDisplayFavicon() || + bool newHasIcon = FaviconTabHelper::ShouldDisplayFavicon(contents) || tabStripModel_->IsMiniTab(modelIndex); // Always show icon if mini. TabLoadingState oldState = [tabController loadingState];
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc index 9a0d2ac..991c74c 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model.cc +++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -943,7 +943,8 @@ // In Windows 8 desktop, add the 'Relaunch Chrome in Windows 8 mode'. // In Windows 7 desktop, add the 'Relaunch Chrome in Windows ASH mode' AddSeparator(ui::NORMAL_SEPARATOR); - if (base::win::GetVersion() >= base::win::VERSION_WIN8) + if (base::win::GetVersion() == base::win::VERSION_WIN8 || + base::win::GetVersion() == base::win::VERSION_WIN8_1) AddItemWithStringId(IDC_WIN8_METRO_RESTART, IDS_WIN8_METRO_RESTART); else AddItemWithStringId(IDC_WIN_CHROMEOS_RESTART, IDS_WIN_CHROMEOS_RESTART);
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc index 95bf482..335eb70d 100644 --- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -30,7 +30,6 @@ #include "ui/base/models/combobox_model.h" #include "ui/base/models/menu_model.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event_handler.h" #include "ui/gfx/animation/animation_delegate.h"
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc index e93920a..e49e0b8 100644 --- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -20,8 +20,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/compositing_recorder.h" -#include "ui/compositor/paint_context.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/views/background.h" #include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/combobox/combobox.h" @@ -85,7 +85,7 @@ void CardUnmaskPromptViews::DisableAndWaitForVerification() { SetInputsEnabled(false); - progress_overlay_->SetOpacity(0.0); + progress_overlay_->SetAlpha(0); progress_overlay_->SetVisible(true); progress_throbber_->Start(); overlay_animation_.Show(); @@ -109,7 +109,7 @@ // TODO(estade): it's somewhat jarring when the error comes back too // quickly. overlay_animation_.Reset(); - storage_row_->SetOpacity(1.0); + storage_row_->SetAlpha(255); progress_overlay_->SetVisible(false); if (allow_retry) { @@ -326,8 +326,9 @@ void CardUnmaskPromptViews::AnimationProgressed( const gfx::Animation* animation) { - progress_overlay_->SetOpacity(animation->GetCurrentValue()); - storage_row_->SetOpacity(1.0 - animation->GetCurrentValue()); + uint8_t alpha = static_cast<uint8_t>(animation->CurrentValueBetween(0, 255)); + progress_overlay_->SetAlpha(alpha); + storage_row_->SetAlpha(255 - alpha); } void CardUnmaskPromptViews::InitIfNecessary() { @@ -456,29 +457,28 @@ } CardUnmaskPromptViews::FadeOutView::FadeOutView() - : fade_everything_(false), opacity_(1.0) { + : fade_everything_(false), alpha_(255) { } CardUnmaskPromptViews::FadeOutView::~FadeOutView() { } void CardUnmaskPromptViews::FadeOutView::PaintChildren( const ui::PaintContext& context) { - uint8_t alpha = static_cast<uint8_t>(255 * opacity_); - ui::CompositingRecorder recorder(context, alpha); + ui::CompositingRecorder recorder(context, alpha_); views::View::PaintChildren(context); } void CardUnmaskPromptViews::FadeOutView::OnPaint(gfx::Canvas* canvas) { - if (!fade_everything_ || opacity_ > 0.99) + if (!fade_everything_ || alpha_ == 255) return views::View::OnPaint(canvas); - canvas->SaveLayerAlpha(0xff * opacity_); + canvas->SaveLayerAlpha(alpha_); views::View::OnPaint(canvas); canvas->Restore(); } -void CardUnmaskPromptViews::FadeOutView::SetOpacity(double opacity) { - opacity_ = opacity; +void CardUnmaskPromptViews::FadeOutView::SetAlpha(uint8_t alpha) { + alpha_ = alpha; SchedulePaint(); }
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h index 03c4434e..6318284 100644 --- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h +++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.h
@@ -87,16 +87,17 @@ void set_fade_everything(bool fade_everything) { fade_everything_ = fade_everything; } - void SetOpacity(double opacity); + + // Set the alpha channel for this view. 0 is transparent and 255 is opaque. + void SetAlpha(uint8_t alpha); private: // Controls whether the background and border are faded out as well. Default // is false, meaning only children are faded. bool fade_everything_; - // On a scale of 0-1, how much to fade out the contents of this view. 0 is - // totally invisible, 1 is totally visible. - double opacity_; + // The alpha channel for this view. 0 is transparent and 255 is opaque. + uint8_t alpha_; DISALLOW_COPY_AND_ASSIGN(FadeOutView); };
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index 490883319..3be1b08 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -72,7 +72,6 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/base/theme_provider.h" #include "ui/base/window_open_disposition.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/gfx/canvas.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc similarity index 75% rename from chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc rename to chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc index 536c1ea..82e3dd9 100644 --- a/chrome/browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/singleton_tabs.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/views/profiles/profile_chooser_view.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" @@ -23,6 +24,12 @@ #include "ui/events/event_constants.h" #include "ui/gfx/range/range.h" +#if defined(OS_CHROMEOS) +const bool kHasProfileChooser = false; +#else +const bool kHasProfileChooser = true; +#endif + class BookmarkBubbleSignInDelegateTest : public InProcessBrowserTest { public: BookmarkBubbleSignInDelegateTest() {} @@ -55,8 +62,12 @@ delegate->OnSignInLinkClicked(); - // A new tab should have been opened and the browser should be visible. - EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count()); + if (kHasProfileChooser) { + EXPECT_TRUE(ProfileChooserView::IsShowing()); + EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count()); + } else { + EXPECT_EQ(starting_tab_count + 1, browser()->tab_strip_model()->count()); + } } IN_PROC_BROWSER_TEST_F(BookmarkBubbleSignInDelegateTest, @@ -68,8 +79,12 @@ delegate->OnSignInLinkClicked(); - // A new tab should have been opened and the browser should be visible. - EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count()); + if (kHasProfileChooser) { + EXPECT_TRUE(ProfileChooserView::IsShowing()); + EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count()); + } else { + EXPECT_EQ(starting_tab_count, browser()->tab_strip_model()->count()); + } } IN_PROC_BROWSER_TEST_F(BookmarkBubbleSignInDelegateTest, @@ -86,11 +101,15 @@ delegate->OnSignInLinkClicked(); - // A new tab should have been opened in the normal browser, which should be - // visible. - int tab_count_normal = browser()->tab_strip_model()->count(); - EXPECT_EQ(starting_tab_count_normal + 1, tab_count_normal); - + if (kHasProfileChooser) { + // ProfileChooser doesn't show in an incognito window. + EXPECT_FALSE(ProfileChooserView::IsShowing()); + } else { + // A new tab should have been opened in the normal browser, which should be + // visible. + int tab_count_normal = browser()->tab_strip_model()->count(); + EXPECT_EQ(starting_tab_count_normal + 1, tab_count_normal); + } // No effect is expected on the incognito browser. int tab_count_incognito = incognito_browser->tab_strip_model()->count(); EXPECT_EQ(starting_tab_count_incognito, tab_count_incognito); @@ -117,8 +136,12 @@ delegate->OnSignInLinkClicked(); - // A new tab should have been opened in the extra browser, which should be - // visible. - int tab_count = extra_browser->tab_strip_model()->count(); - EXPECT_EQ(starting_tab_count + 1, tab_count); + if (kHasProfileChooser) { + EXPECT_TRUE(ProfileChooserView::IsShowing()); + } else { + // A new tab should have been opened in the extra browser, which should be + // visible. + int tab_count = extra_browser->tab_strip_model()->count(); + EXPECT_EQ(starting_tab_count + 1, tab_count); + } }
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc index 88b4529..8983b44e 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.cc +++ b/chrome/browser/ui/views/create_application_shortcut_view.cc
@@ -252,15 +252,16 @@ create_shortcuts_label_(NULL), desktop_check_box_(NULL), menu_check_box_(NULL), - quick_launch_check_box_(NULL) {} + quick_launch_check_box_(NULL) { +} CreateApplicationShortcutView::~CreateApplicationShortcutView() {} void CreateApplicationShortcutView::InitControls(DialogLayout dialog_layout) { - if (dialog_layout == DIALOG_LAYOUT_URL_SHORTCUT) { - app_info_ = new AppInfoView(shortcut_info_.title, - shortcut_info_.description, - shortcut_info_.favicon); + if (dialog_layout == DIALOG_LAYOUT_URL_SHORTCUT && shortcut_info_) { + app_info_ = + new AppInfoView(shortcut_info_->title, shortcut_info_->description, + shortcut_info_->favicon); } create_shortcuts_label_ = new views::Label( l10n_util::GetStringUTF16(IDS_CREATE_SHORTCUTS_LABEL)); @@ -370,6 +371,12 @@ } bool CreateApplicationShortcutView::Accept() { + // NOTE: This procedure will reset |shortcut_info_| to null. + + // Can happen if the shortcut data is not yet loaded. + if (!shortcut_info_) + return false; + if (!IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)) return false; @@ -392,8 +399,7 @@ #endif web_app::CreateShortcutsWithInfo(web_app::SHORTCUT_CREATION_BY_USER, - creation_locations, - shortcut_info_, + creation_locations, shortcut_info_.Pass(), file_handlers_info_); return true; } @@ -430,7 +436,7 @@ web_contents_(web_contents), pending_download_id_(-1), weak_ptr_factory_(this) { - web_app::GetShortcutInfoForTab(web_contents_, &shortcut_info_); + shortcut_info_ = web_app::GetShortcutInfoForTab(web_contents_); const WebApplicationInfo& app_info = extensions::TabHelper::FromWebContents(web_contents_)->web_app_info(); if (!app_info.icons.empty()) { @@ -448,12 +454,15 @@ } bool CreateUrlApplicationShortcutView::Accept() { + // Get the smallest icon in the icon family (should have only 1). This must be + // done before the call to Accept(), which will reset |shortcut_info_|. + DCHECK(shortcut_info_); + const gfx::Image* icon = shortcut_info_->favicon.GetBest(0, 0); + SkBitmap bitmap = icon ? icon->AsBitmap() : SkBitmap(); + if (!CreateApplicationShortcutView::Accept()) return false; - // Get the smallest icon in the icon family (should have only 1). - const gfx::Image* icon = shortcut_info_.favicon.GetBest(0, 0); - SkBitmap bitmap = icon ? icon->AsBitmap() : SkBitmap(); extensions::TabHelper::FromWebContents(web_contents_)->SetAppIcon(bitmap); Browser* browser = chrome::FindBrowserWithWebContents(web_contents_); if (browser) @@ -493,6 +502,10 @@ return; pending_download_id_ = -1; + // Can happen if the dialog has already been accepted. + if (!shortcut_info_) + return; + gfx::ImageSkia image_skia = CreateFaviconImageSkia( bitmaps, original_bitmap_sizes, @@ -502,8 +515,8 @@ // As |shortcut_info_| will be passed to the FILE thread upon accepting the // dialog, this image must be made read-only and thread-safe. image_skia.MakeThreadSafe(); - shortcut_info_.favicon.Add(image_skia); - static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); + shortcut_info_->favicon.Add(image_skia); + static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_->favicon); } else { FetchIcon(); } @@ -545,8 +558,8 @@ } void CreateChromeApplicationShortcutView::OnAppInfoLoaded( - const web_app::ShortcutInfo& shortcut_info, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { - shortcut_info_ = shortcut_info; + shortcut_info_ = shortcut_info.Pass(); file_handlers_info_ = file_handlers_info; }
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.h b/chrome/browser/ui/views/create_application_shortcut_view.h index d97a9e6e..3952bb1 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.h +++ b/chrome/browser/ui/views/create_application_shortcut_view.h
@@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "chrome/browser/web_applications/web_app.h" #include "extensions/common/manifest_handlers/file_handler_info.h" #include "ui/views/controls/button/button.h" @@ -86,7 +87,7 @@ views::Checkbox* quick_launch_check_box_; // Target shortcut and file handler info. - web_app::ShortcutInfo shortcut_info_; + scoped_ptr<web_app::ShortcutInfo> shortcut_info_; extensions::FileHandlersInfo file_handlers_info_; // If false, the shortcut will be created in the root level of the Start Menu. bool create_in_chrome_apps_subdir_; @@ -145,7 +146,7 @@ private: // Called when the app's ShortcutInfo (with icon) and FileHandlersInfo is // loaded. - void OnAppInfoLoaded(const web_app::ShortcutInfo& shortcut_info, + void OnAppInfoLoaded(scoped_ptr<web_app::ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info); base::Callback<void(bool)> close_callback_;
diff --git a/chrome/browser/ui/views/extensions/device_permissions_dialog_view.cc b/chrome/browser/ui/views/extensions/device_permissions_dialog_view.cc index a4acefe..9443cee 100644 --- a/chrome/browser/ui/views/extensions/device_permissions_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/device_permissions_dialog_view.cc
@@ -44,7 +44,7 @@ private: scoped_refptr<DevicePermissionsPrompt::Prompt> prompt_; - ui::TableModelObserver* observer_; + ui::TableModelObserver* observer_ = nullptr; }; int DevicePermissionsTableModel::RowCount() {
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc index 65fda498..84e7b00 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.cc +++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -18,7 +18,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/clip_transform_recorder.h" -#include "ui/compositor/paint_context.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/resources/grit/ui_resources.h"
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 1928b32..52f7afb 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -74,7 +74,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/theme_provider.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event.h" #include "ui/gfx/animation/slide_animation.h"
diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.cc b/chrome/browser/ui/views/location_bar/page_action_image_view.cc index 266a521..c0403057 100644 --- a/chrome/browser/ui/views/location_bar/page_action_image_view.cc +++ b/chrome/browser/ui/views/location_bar/page_action_image_view.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "extensions/browser/extension_registry.h" #include "ui/accessibility/ax_view_state.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event.h" #include "ui/gfx/canvas.h"
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc index 3aa37e2ba..fdaaf5b 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" #include "ui/base/theme_provider.h" #include "ui/compositor/clip_transform_recorder.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h"
diff --git a/chrome/browser/ui/views/profiles/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/profiles/avatar_menu_button_browsertest.cc index 7ad8447..cfe903ae 100644 --- a/chrome/browser/ui/views/profiles/avatar_menu_button_browsertest.cc +++ b/chrome/browser/ui/views/profiles/avatar_menu_button_browsertest.cc
@@ -17,6 +17,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/test_switches.h" #include "chrome/test/base/testing_browser_process.h" +#include "components/signin/core/common/profile_management_switches.h" class AvatarMenuButtonTest : public InProcessBrowserTest { public: @@ -24,6 +25,7 @@ ~AvatarMenuButtonTest() override; protected: + void SetUpCommandLine(base::CommandLine* command_line) override; void CreateTestingProfile(); AvatarMenuButton* GetAvatarMenuButton(); void StartAvatarMenu(); @@ -38,6 +40,10 @@ AvatarMenuButtonTest::~AvatarMenuButtonTest() { } +void AvatarMenuButtonTest::SetUpCommandLine(base::CommandLine* command_line) { + switches::DisableNewAvatarMenuForTesting(command_line); +} + void AvatarMenuButtonTest::CreateTestingProfile() { ProfileManager* profile_manager = g_browser_process->profile_manager(); EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles());
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index f0f5e5a..2edc650 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -44,7 +44,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/clip_transform_recorder.h" -#include "ui/compositor/paint_context.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h"
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index ee646d4..23a17e93 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -509,7 +509,8 @@ data->crashed_status = contents->GetCrashedStatus(); data->incognito = contents->GetBrowserContext()->IsOffTheRecord(); data->mini = model_->IsMiniTab(model_index); - data->show_icon = data->mini || favicon_tab_helper->ShouldDisplayFavicon(); + data->show_icon = + data->mini || FaviconTabHelper::ShouldDisplayFavicon(contents); data->blocked = model_->IsTabBlocked(model_index); data->app = extensions::TabHelper::FromWebContents(contents)->is_app(); data->media_state = chrome::GetTabMediaStateForContents(contents);
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index c4f654b..44aa52f 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -324,6 +324,11 @@ IDS_LOGIN_CONSUMER_MANAGEMENT_ENROLLMENT); builder->Add("backButton", IDS_ACCNAME_BACK); builder->Add("closeButton", IDS_CLOSE); + builder->Add("whitelistErrorConsumer", IDS_LOGIN_ERROR_WHITELIST); + builder->Add("whitelistErrorEnterprise", + IDS_ENTERPRISE_LOGIN_ERROR_WHITELIST); + builder->Add("tryAgainButton", IDS_WHITELIST_ERROR_TRY_AGAIN_BUTTON); + builder->Add("learnMoreButton", IDS_WHITELIST_ERROR_LEARN_MORE_BUTTON); builder->Add("gaiaLoadingNewGaia", IDS_LOGIN_GAIA_LOADING_MESSAGE); // Strings used by the SAML fatal error dialog. @@ -535,7 +540,7 @@ focus_stolen_ = false; const char code[] = "if (typeof gWindowOnLoad != 'undefined') gWindowOnLoad();"; - content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe( + content::RenderFrameHost* frame = InlineLoginUI::GetAuthFrame( web_ui()->GetWebContents(), GURL(kAuthIframeParentOrigin), kAuthIframeParentName); @@ -549,7 +554,7 @@ const char code[] = "var gWindowOnLoad = window.onload; " "window.onload=function() {};"; - content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe( + content::RenderFrameHost* frame = InlineLoginUI::GetAuthFrame( web_ui()->GetWebContents(), GURL(kAuthIframeParentOrigin), kAuthIframeParentName); @@ -687,16 +692,33 @@ void GaiaScreenHandler::SubmitLoginFormForTest() { VLOG(2) << "Submit login form for test, user=" << test_user_; - std::string code; - code += "document.getElementById('Email').value = '" + test_user_ + "';"; - code += "document.getElementById('Passwd').value = '" + test_pass_ + "';"; - code += "document.getElementById('signIn').click();"; - - content::RenderFrameHost* frame = InlineLoginUI::GetAuthIframe( + content::RenderFrameHost* frame = InlineLoginUI::GetAuthFrame( web_ui()->GetWebContents(), GURL(kAuthIframeParentOrigin), kAuthIframeParentName); - frame->ExecuteJavaScript(base::ASCIIToUTF16(code)); + + if (!StartupUtils::IsWebviewSigninEnabled()) { + std::string code; + code += "document.getElementById('Email').value = '" + test_user_ + "';"; + code += "document.getElementById('Passwd').value = '" + test_pass_ + "';"; + code += "document.getElementById('signIn').click();"; + + frame->ExecuteJavaScript(base::ASCIIToUTF16(code)); + } else { + std::string code; + + code = + "document.getElementById('identifier').value = '" + test_user_ + "';"; + code += "document.getElementById('nextButton').click();"; + frame->ExecuteJavaScript(base::ASCIIToUTF16(code)); + + if (!test_pass_.empty()) { + code = + "document.getElementById('password').value = '" + test_pass_ + "';"; + code += "document.getElementById('nextButton').click();"; + frame->ExecuteJavaScript(base::ASCIIToUTF16(code)); + } + } // Test properties are cleared in HandleCompleteLogin because the form // submission might fail and login will not be attempted after reloading @@ -821,6 +843,15 @@ } } +void GaiaScreenHandler::ShowWhitelistCheckFailedError() { + base::DictionaryValue params; + params.SetBoolean("enterpriseManaged", + g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->IsEnterpriseManaged()); + CallJS("showWhitelistCheckFailedError", true, params); +} + void GaiaScreenHandler::LoadAuthExtension(bool force, bool silent_load, bool offline) {
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index bdc605a..d7b1b28 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -85,6 +85,9 @@ // pre-loads it. void MaybePreloadAuthExtension(); + // Show error UI at the end of GAIA flow when user is not whitelisted. + void ShowWhitelistCheckFailedError(); + FrameState frame_state() const { return frame_state_; } net::Error frame_error() const { return frame_error_; }
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 629f4fc3..52ba8bfc 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -928,6 +928,11 @@ gaia_screen_handler_->ShowSigninScreenForCreds(username, password); } +void SigninScreenHandler::ShowWhitelistCheckFailedError() { + DCHECK(gaia_screen_handler_); + gaia_screen_handler_->ShowWhitelistCheckFailedError(); +} + void SigninScreenHandler::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) {
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index 93f1571..695345745 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -92,6 +92,7 @@ // Show sign-in screen for the given credentials. virtual void ShowSigninScreenForCreds(const std::string& username, const std::string& password) = 0; + virtual void ShowWhitelistCheckFailedError() = 0; virtual void LoadUsers(const base::ListValue& users_list, bool show_guest) = 0; protected: @@ -300,6 +301,7 @@ void ShowErrorScreen(LoginDisplay::SigninError error_id) override; void ShowSigninScreenForCreds(const std::string& username, const std::string& password) override; + void ShowWhitelistCheckFailedError() override; void LoadUsers(const base::ListValue& users_list, bool show_guest) override; // content::NotificationObserver implementation:
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc index 9f1df4e..864c2a23 100644 --- a/chrome/browser/ui/webui/options/content_settings_handler.cc +++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -1177,8 +1177,12 @@ std::vector<std::vector<base::Value*> > all_provider_exceptions; all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES); - for (AllPatternsSettings::iterator i = all_patterns_settings.begin(); - i != all_patterns_settings.end(); + // The all_patterns_settings is sorted from the lowest precedence pattern to + // the highest (see operator< in ContentSettingsPattern), so traverse it in + // reverse to show the patterns with the highest precedence (the more specific + // ones) on the top. + for (AllPatternsSettings::reverse_iterator i = all_patterns_settings.rbegin(); + i != all_patterns_settings.rend(); ++i) { const ContentSettingsPattern& primary_pattern = i->first.first; const OnePatternSettings& one_settings = i->second;
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc index af92e1fc1..a76a764 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc +++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -496,9 +496,9 @@ // Returns early if this is not a gaia iframe navigation. const GURL kGaiaExtOrigin( "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/"); - content::RenderFrameHost* gaia_iframe = InlineLoginUI::GetAuthIframe( + content::RenderFrameHost* gaia_frame = InlineLoginUI::GetAuthFrame( web_contents(), kGaiaExtOrigin, "signin-frame"); - if (render_frame_host != gaia_iframe) + if (render_frame_host != gaia_frame) return; // Loading any untrusted (e.g., HTTP) URLs in the privileged sign-in process
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc index d45b25e3..6bd7c52 100644 --- a/chrome/browser/ui/webui/signin/inline_login_ui.cc +++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -127,7 +127,7 @@ InlineLoginUI::~InlineLoginUI() {} // Gets the Gaia iframe within a WebContents. -content::RenderFrameHost* InlineLoginUI::GetAuthIframe( +content::RenderFrameHost* InlineLoginUI::GetAuthFrame( content::WebContents* web_contents, const GURL& parent_origin, const std::string& parent_frame_name) {
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.h b/chrome/browser/ui/webui/signin/inline_login_ui.h index d4c44082..20a9f23f 100644 --- a/chrome/browser/ui/webui/signin/inline_login_ui.h +++ b/chrome/browser/ui/webui/signin/inline_login_ui.h
@@ -21,9 +21,10 @@ explicit InlineLoginUI(content::WebUI* web_ui); ~InlineLoginUI() override; - // Gets the iframe within an auth page that has the specified parent origin - // if |parent_origin| is not empty, and the specified parent frame name. - static content::RenderFrameHost* GetAuthIframe( + // Gets the frame (iframe or webview) within an auth page that has the + // specified parent origin if |parent_origin| is not empty, and the specified + // parent frame name. + static content::RenderFrameHost* GetAuthFrame( content::WebContents* web_contents, const GURL& parent_origin, const std::string& parent_frame_name);
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index 376bd4b..7f5e2bfd 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -114,7 +114,7 @@ content::WebContents* web_contents = browser->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthIframe( + ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthFrame( web_contents, GURL(), "signin-frame"), js)); }
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc index 95a25f43..feddfc81 100644 --- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc +++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -100,15 +100,15 @@ } std::string GetAvatarImageAtIndex( - size_t index, const ProfileInfoCache& info_cache) { + size_t index, ProfileInfoCache* info_cache) { bool is_gaia_picture = - info_cache.IsUsingGAIAPictureOfProfileAtIndex(index) && - info_cache.GetGAIAPictureOfProfileAtIndex(index); + info_cache->IsUsingGAIAPictureOfProfileAtIndex(index) && + info_cache->GetGAIAPictureOfProfileAtIndex(index); // If the avatar is too small (i.e. the old-style low resolution avatar), // it will be pixelated when displayed in the User Manager, so we should // return the placeholder avatar instead. - gfx::Image avatar_image = info_cache.GetAvatarIconOfProfileAtIndex(index); + gfx::Image avatar_image = info_cache->GetAvatarIconOfProfileAtIndex(index); if (avatar_image.Width() <= profiles::kAvatarIconWidth || avatar_image.Height() <= profiles::kAvatarIconHeight ) { avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed( @@ -725,8 +725,8 @@ void UserManagerScreenHandler::SendUserList() { base::ListValue users_list; - const ProfileInfoCache& info_cache = - g_browser_process->profile_manager()->GetProfileInfoCache(); + ProfileInfoCache* info_cache = + &g_browser_process->profile_manager()->GetProfileInfoCache(); user_auth_type_map_.clear(); // Profile deletion is not allowed in Metro mode. @@ -735,14 +735,14 @@ can_remove = !ash::Shell::HasInstance(); #endif - for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) { + for (size_t i = 0; i < info_cache->GetNumberOfProfiles(); ++i) { base::DictionaryValue* profile_value = new base::DictionaryValue(); - base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i); + base::FilePath profile_path = info_cache->GetPathOfProfileAtIndex(i); profile_value->SetString( - kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i)); + kKeyUsername, info_cache->GetUserNameOfProfileAtIndex(i)); profile_value->SetString( - kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i)); + kKeyEmailAddress, info_cache->GetUserNameOfProfileAtIndex(i)); profile_value->SetString( kKeyDisplayName, profiles::GetAvatarNameForProfile(profile_path)); @@ -750,11 +750,11 @@ kKeyProfilePath, base::CreateFilePathValue(profile_path)); profile_value->SetBoolean(kKeyPublicAccount, false); profile_value->SetBoolean(kKeyLegacySupervisedUser, - info_cache.ProfileIsLegacySupervisedAtIndex(i)); + info_cache->ProfileIsLegacySupervisedAtIndex(i)); profile_value->SetBoolean( - kKeyChildUser, info_cache.ProfileIsChildAtIndex(i)); + kKeyChildUser, info_cache->ProfileIsChildAtIndex(i)); profile_value->SetBoolean( - kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i)); + kKeyNeedsSignin, info_cache->ProfileIsSigninRequiredAtIndex(i)); profile_value->SetBoolean(kKeyIsOwner, false); profile_value->SetBoolean(kKeyCanRemove, can_remove); profile_value->SetBoolean(kKeyIsDesktop, true);
diff --git a/chrome/browser/web_applications/update_shortcut_worker_win.cc b/chrome/browser/web_applications/update_shortcut_worker_win.cc index 39d6ec0..528b60b 100644 --- a/chrome/browser/web_applications/update_shortcut_worker_win.cc +++ b/chrome/browser/web_applications/update_shortcut_worker_win.cc
@@ -39,10 +39,10 @@ web_contents->GetBrowserContext())->GetPath()) { extensions::TabHelper* extensions_tab_helper = extensions::TabHelper::FromWebContents(web_contents); - web_app::GetShortcutInfoForTab(web_contents_, &shortcut_info_); + shortcut_info_ = web_app::GetShortcutInfoForTab(web_contents_); web_app::GetIconsInfo(extensions_tab_helper->web_app_info(), &unprocessed_icons_); - file_name_ = web_app::internals::GetSanitizedFileName(shortcut_info_.title); + file_name_ = web_app::internals::GetSanitizedFileName(shortcut_info_->title); registrar_.Add( this, @@ -118,7 +118,7 @@ if (!bitmap.isNull()) { // Update icon with download image and update shortcut. - shortcut_info_.favicon.Add(gfx::Image::CreateFrom1xBitmap(bitmap)); + shortcut_info_->favicon.Add(gfx::Image::CreateFrom1xBitmap(bitmap)); extensions::TabHelper* extensions_tab_helper = extensions::TabHelper::FromWebContents(web_contents_); extensions_tab_helper->SetAppIcon(bitmap); @@ -180,7 +180,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::FilePath web_app_path = web_app::GetWebAppDataDirectory( - profile_path_, shortcut_info_.extension_id, shortcut_info_.url); + profile_path_, shortcut_info_->extension_id, shortcut_info_->url); // Ensure web_app_path exists. web_app_path could be missing for a legacy // shortcut created by Gears. @@ -191,8 +191,9 @@ } base::FilePath icon_file = - web_app::internals::GetIconFilePath(web_app_path, shortcut_info_.title); - web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_.favicon, true); + web_app::internals::GetIconFilePath(web_app_path, shortcut_info_->title); + web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_->favicon, + true); // Update existing shortcuts' description, icon and app id. CheckExistingShortcuts(); @@ -200,17 +201,17 @@ // Generates app id from web app url and profile path. base::string16 app_id = ShellIntegration::GetAppModelIdForProfile( base::UTF8ToWide( - web_app::GenerateApplicationNameFromURL(shortcut_info_.url)), + web_app::GenerateApplicationNameFromURL(shortcut_info_->url)), profile_path_); // Sanitize description - if (shortcut_info_.description.length() >= MAX_PATH) - shortcut_info_.description.resize(MAX_PATH - 1); + if (shortcut_info_->description.length() >= MAX_PATH) + shortcut_info_->description.resize(MAX_PATH - 1); for (size_t i = 0; i < shortcut_files_.size(); ++i) { base::win::ShortcutProperties shortcut_properties; shortcut_properties.set_target(shortcut_files_[i]); - shortcut_properties.set_description(shortcut_info_.description); + shortcut_properties.set_description(shortcut_info_->description); shortcut_properties.set_icon(icon_file, 0); shortcut_properties.set_app_id(app_id); base::win::CreateOrUpdateShortcutLink(
diff --git a/chrome/browser/web_applications/update_shortcut_worker_win.h b/chrome/browser/web_applications/update_shortcut_worker_win.h index 1169ee3..62fc6b7 100644 --- a/chrome/browser/web_applications/update_shortcut_worker_win.h +++ b/chrome/browser/web_applications/update_shortcut_worker_win.h
@@ -70,7 +70,7 @@ web_app::IconInfoList unprocessed_icons_; // Cached shortcut data from the web_contents_. - web_app::ShortcutInfo shortcut_info_; + scoped_ptr<web_app::ShortcutInfo> shortcut_info_; // Our copy of profile path. base::FilePath profile_path_;
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index 6278d48..7522fa24 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc
@@ -83,17 +83,17 @@ void UpdateAllShortcutsForShortcutInfo( const base::string16& old_app_title, - const web_app::ShortcutInfo& shortcut_info, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { + base::FilePath shortcut_data_dir = GetShortcutDataDir(*shortcut_info); BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, + BrowserThread::FILE, FROM_HERE, base::Bind(&web_app::internals::UpdatePlatformShortcuts, - GetShortcutDataDir(shortcut_info), - old_app_title, shortcut_info, file_handlers_info)); + shortcut_data_dir, old_app_title, base::Passed(&shortcut_info), + file_handlers_info)); } -void OnImageLoaded(web_app::ShortcutInfo shortcut_info, +void OnImageLoaded(scoped_ptr<web_app::ShortcutInfo> shortcut_info, extensions::FileHandlersInfo file_handlers_info, web_app::InfoCallback callback, const gfx::ImageFamily& image_family) { @@ -110,31 +110,32 @@ // We are on the UI thread, and this image is needed from the FILE thread, // for creating shortcut icon files. image_skia.MakeThreadSafe(); - shortcut_info.favicon.Add(gfx::Image(image_skia)); + shortcut_info->favicon.Add(gfx::Image(image_skia)); } else { - shortcut_info.favicon = image_family; + shortcut_info->favicon = image_family; } - callback.Run(shortcut_info, file_handlers_info); + callback.Run(shortcut_info.Pass(), file_handlers_info); } void IgnoreFileHandlersInfo( const web_app::ShortcutInfoCallback& shortcut_info_callback, - const web_app::ShortcutInfo& shortcut_info, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { - shortcut_info_callback.Run(shortcut_info); + shortcut_info_callback.Run(shortcut_info.Pass()); } void ScheduleCreatePlatformShortcut( web_app::ShortcutCreationReason reason, const web_app::ShortcutLocations& locations, - const web_app::ShortcutInfo& shortcut_info, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { + base::FilePath shortcut_data_dir = GetShortcutDataDir(*shortcut_info); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind( base::IgnoreResult(&web_app::internals::CreatePlatformShortcuts), - GetShortcutDataDir(shortcut_info), shortcut_info, file_handlers_info, + shortcut_data_dir, base::Passed(&shortcut_info), file_handlers_info, locations, reason)); } @@ -177,16 +178,15 @@ } #if defined(TOOLKIT_VIEWS) -void GetShortcutInfoForTab(content::WebContents* web_contents, - ShortcutInfo* info) { - DCHECK(info); // Must provide a valid info. - +scoped_ptr<ShortcutInfo> GetShortcutInfoForTab( + content::WebContents* web_contents) { const FaviconTabHelper* favicon_tab_helper = FaviconTabHelper::FromWebContents(web_contents); const extensions::TabHelper* extensions_tab_helper = extensions::TabHelper::FromWebContents(web_contents); const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); + scoped_ptr<ShortcutInfo> info(new ShortcutInfo); info->url = app_info.app_url.is_empty() ? web_contents->GetURL() : app_info.app_url; info->title = app_info.title.empty() ? @@ -199,6 +199,8 @@ Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); info->profile_path = profile->GetPath(); + + return info; } #endif @@ -206,27 +208,28 @@ void UpdateShortcutForTabContents(content::WebContents* web_contents) {} #endif -ShortcutInfo ShortcutInfoForExtensionAndProfile( - const extensions::Extension* app, Profile* profile) { - ShortcutInfo shortcut_info; - shortcut_info.extension_id = app->id(); - shortcut_info.is_platform_app = app->is_platform_app(); - shortcut_info.url = extensions::AppLaunchInfo::GetLaunchWebURL(app); - shortcut_info.title = base::UTF8ToUTF16(app->name()); - shortcut_info.description = base::UTF8ToUTF16(app->description()); - shortcut_info.extension_path = app->path(); - shortcut_info.profile_path = profile->GetPath(); - shortcut_info.profile_name = +scoped_ptr<ShortcutInfo> ShortcutInfoForExtensionAndProfile( + const extensions::Extension* app, + Profile* profile) { + scoped_ptr<ShortcutInfo> shortcut_info(new ShortcutInfo); + shortcut_info->extension_id = app->id(); + shortcut_info->is_platform_app = app->is_platform_app(); + shortcut_info->url = extensions::AppLaunchInfo::GetLaunchWebURL(app); + shortcut_info->title = base::UTF8ToUTF16(app->name()); + shortcut_info->description = base::UTF8ToUTF16(app->description()); + shortcut_info->extension_path = app->path(); + shortcut_info->profile_path = profile->GetPath(); + shortcut_info->profile_name = profile->GetPrefs()->GetString(prefs::kProfileName); - shortcut_info.version_for_display = app->GetVersionForDisplay(); + shortcut_info->version_for_display = app->GetVersionForDisplay(); return shortcut_info; } void GetInfoForApp(const extensions::Extension* extension, Profile* profile, const InfoCallback& callback) { - web_app::ShortcutInfo shortcut_info = - web_app::ShortcutInfoForExtensionAndProfile(extension, profile); + scoped_ptr<web_app::ShortcutInfo> shortcut_info( + web_app::ShortcutInfoForExtensionAndProfile(extension, profile)); const std::vector<extensions::FileHandlerInfo>* file_handlers = extensions::FileHandlers::GetFileHandlers(extension); extensions::FileHandlersInfo file_handlers_info = @@ -272,9 +275,9 @@ // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty // image and exit immediately. extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( - extension, - info_list, - base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); + extension, info_list, + base::Bind(&OnImageLoaded, base::Passed(&shortcut_info), + file_handlers_info, callback)); } void GetShortcutInfoForApp(const extensions::Extension* extension, @@ -378,37 +381,38 @@ void CreateShortcutsWithInfo( ShortcutCreationReason reason, const ShortcutLocations& locations, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // If the shortcut is for an application shortcut with the new bookmark app // flow disabled, there will be no corresponding extension. - if (!shortcut_info.extension_id.empty()) { + if (!shortcut_info->extension_id.empty()) { // It's possible for the extension to be deleted before we get here. // For example, creating a hosted app from a website. Double check that // it still exists. Profile* profile = g_browser_process->profile_manager()->GetProfileByPath( - shortcut_info.profile_path); + shortcut_info->profile_path); if (!profile) return; extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile); const extensions::Extension* extension = registry->GetExtensionById( - shortcut_info.extension_id, extensions::ExtensionRegistry::EVERYTHING); + shortcut_info->extension_id, extensions::ExtensionRegistry::EVERYTHING); if (!extension) return; } - ScheduleCreatePlatformShortcut(reason, locations, shortcut_info, + ScheduleCreatePlatformShortcut(reason, locations, shortcut_info.Pass(), file_handlers_info); } void CreateNonAppShortcut(const ShortcutLocations& locations, - const ShortcutInfo& shortcut_info) { + scoped_ptr<ShortcutInfo> shortcut_info) { ScheduleCreatePlatformShortcut(SHORTCUT_CREATION_AUTOMATED, locations, - shortcut_info, extensions::FileHandlersInfo()); + shortcut_info.Pass(), + extensions::FileHandlersInfo()); } void CreateShortcuts(ShortcutCreationReason reason, @@ -427,13 +431,13 @@ void DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - ShortcutInfo shortcut_info = - ShortcutInfoForExtensionAndProfile(app, profile); + scoped_ptr<ShortcutInfo> shortcut_info( + ShortcutInfoForExtensionAndProfile(app, profile)); + base::FilePath shortcut_data_dir = GetShortcutDataDir(*shortcut_info); BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, + BrowserThread::FILE, FROM_HERE, base::Bind(&web_app::internals::DeletePlatformShortcuts, - GetShortcutDataDir(shortcut_info), shortcut_info)); + shortcut_data_dir, base::Passed(&shortcut_info))); } void UpdateAllShortcuts(const base::string16& old_app_title,
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index a7d93fb..72f728cb 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "build/build_config.h" #include "chrome/browser/shell_integration.h" @@ -53,6 +54,12 @@ base::FilePath profile_path; std::string profile_name; std::string version_for_display; + + private: + // ShortcutInfo must not be copied; generally it is passed around via + // scoped_ptrs. This is to allow passing ShortcutInfos between threads, + // despite ImageFamily having a non-thread-safe reference count. + DISALLOW_COPY_AND_ASSIGN(ShortcutInfo); }; // This specifies a folder in the system applications menu (e.g the Start Menu @@ -98,16 +105,16 @@ }; // Called by GetInfoForApp after fetching the ShortcutInfo and FileHandlersInfo. -typedef base::Callback<void(const ShortcutInfo&, +typedef base::Callback<void(scoped_ptr<ShortcutInfo>, const extensions::FileHandlersInfo&)> InfoCallback; // Called by GetShortcutInfoForApp after fetching the ShortcutInfo. -typedef base::Callback<void(const ShortcutInfo&)> ShortcutInfoCallback; +typedef base::Callback<void(scoped_ptr<ShortcutInfo>)> ShortcutInfoCallback; #if defined(TOOLKIT_VIEWS) // Extracts shortcut info of the given WebContents. -void GetShortcutInfoForTab(content::WebContents* web_contents, - ShortcutInfo* info); +scoped_ptr<ShortcutInfo> GetShortcutInfoForTab( + content::WebContents* web_contents); #endif // Updates web app shortcut of the WebContents. This function checks and @@ -117,7 +124,7 @@ // updates (recreates) them if they exits. void UpdateShortcutForTabContents(content::WebContents* web_contents); -ShortcutInfo ShortcutInfoForExtensionAndProfile( +scoped_ptr<ShortcutInfo> ShortcutInfoForExtensionAndProfile( const extensions::Extension* app, Profile* profile); @@ -173,13 +180,13 @@ void CreateShortcutsWithInfo( ShortcutCreationReason reason, const ShortcutLocations& locations, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info); // Currently only called by app_list_service_mac to create a shim for the // app launcher. void CreateNonAppShortcut(const ShortcutLocations& locations, - const ShortcutInfo& shortcut_info); + scoped_ptr<ShortcutInfo> shortcut_info); // Creates shortcuts for an app. This loads the app's icon from disk, and calls // CreateShortcutsWithInfo(). If you already have a ShortcutInfo with the app's @@ -239,7 +246,7 @@ // |creation_locations| contains information about where to create them. bool CreatePlatformShortcuts( const base::FilePath& shortcut_data_path, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info, const ShortcutLocations& creation_locations, ShortcutCreationReason creation_reason); @@ -248,7 +255,7 @@ // platform specific implementation of the DeleteAllShortcuts function, and // is executed on the FILE thread. void DeletePlatformShortcuts(const base::FilePath& shortcut_data_path, - const ShortcutInfo& shortcut_info); + scoped_ptr<ShortcutInfo> shortcut_info); // Updates all the shortcuts we have added for this extension. This is the // platform specific implementation of the UpdateAllShortcuts function, and @@ -256,7 +263,7 @@ void UpdatePlatformShortcuts( const base::FilePath& shortcut_data_path, const base::string16& old_app_title, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info); // Delete all the shortcuts for an entire profile.
diff --git a/chrome/browser/web_applications/web_app_chromeos.cc b/chrome/browser/web_applications/web_app_chromeos.cc index de41081..e86b9eb 100644 --- a/chrome/browser/web_applications/web_app_chromeos.cc +++ b/chrome/browser/web_applications/web_app_chromeos.cc
@@ -15,7 +15,7 @@ bool CreatePlatformShortcuts( const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info, const ShortcutLocations& creation_locations, ShortcutCreationReason creation_reason) { @@ -23,12 +23,12 @@ } void DeletePlatformShortcuts(const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info) {} + scoped_ptr<ShortcutInfo> shortcut_info) {} void UpdatePlatformShortcuts( const base::FilePath& web_app_path, const base::string16& old_app_title, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) {} void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) {}
diff --git a/chrome/browser/web_applications/web_app_linux.cc b/chrome/browser/web_applications/web_app_linux.cc index 1cd7e05..e6636dd 100644 --- a/chrome/browser/web_applications/web_app_linux.cc +++ b/chrome/browser/web_applications/web_app_linux.cc
@@ -20,31 +20,31 @@ bool CreatePlatformShortcuts( const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info, const ShortcutLocations& creation_locations, ShortcutCreationReason /*creation_reason*/) { #if !defined(OS_CHROMEOS) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - return shell_integration_linux::CreateDesktopShortcut( - shortcut_info, creation_locations); + return shell_integration_linux::CreateDesktopShortcut(*shortcut_info, + creation_locations); #else return false; #endif } void DeletePlatformShortcuts(const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info) { + scoped_ptr<ShortcutInfo> shortcut_info) { #if !defined(OS_CHROMEOS) - shell_integration_linux::DeleteDesktopShortcuts(shortcut_info.profile_path, - shortcut_info.extension_id); + shell_integration_linux::DeleteDesktopShortcuts(shortcut_info->profile_path, + shortcut_info->extension_id); #endif } void UpdatePlatformShortcuts( const base::FilePath& web_app_path, const base::string16& /*old_app_title*/, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); @@ -53,7 +53,7 @@ // Find out whether shortcuts are already installed. ShortcutLocations creation_locations = shell_integration_linux::GetExistingShortcutLocations( - env.get(), shortcut_info.profile_path, shortcut_info.extension_id); + env.get(), shortcut_info->profile_path, shortcut_info->extension_id); // Always create a hidden shortcut in applications if a visible one is not // being created. This allows the operating system to identify the app, but @@ -61,10 +61,8 @@ if (creation_locations.applications_menu_location == APP_MENU_LOCATION_NONE) creation_locations.applications_menu_location = APP_MENU_LOCATION_HIDDEN; - CreatePlatformShortcuts(web_app_path, - shortcut_info, - file_handlers_info, - creation_locations, + CreatePlatformShortcuts(web_app_path, shortcut_info.Pass(), + file_handlers_info, creation_locations, SHORTCUT_CREATION_AUTOMATED); }
diff --git a/chrome/browser/web_applications/web_app_mac.h b/chrome/browser/web_applications/web_app_mac.h index 49964a30..845907a 100644 --- a/chrome/browser/web_applications/web_app_mac.h +++ b/chrome/browser/web_applications/web_app_mac.h
@@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" #include "chrome/browser/web_applications/web_app.h" #include "extensions/common/manifest_handlers/file_handler_info.h" @@ -30,7 +31,7 @@ base::FilePath GetAppInstallPath(const ShortcutInfo& shortcut_info); // If necessary, launch the shortcut for an app. -void MaybeLaunchShortcut(const ShortcutInfo& shortcut_info); +void MaybeLaunchShortcut(scoped_ptr<ShortcutInfo> shortcut_info); // Rebuild the shortcut and relaunch it. bool MaybeRebuildShortcut(const base::CommandLine& command_line); @@ -48,8 +49,10 @@ // Creates a new shortcut based on information in |shortcut_info|. // A copy of the shortcut is placed in |app_data_dir|. // |chrome_bundle_id| is the CFBundleIdentifier of the Chrome browser bundle. + // Retains the pointer |shortcut_info|; the ShortcutInfo object must outlive + // the WebAppShortcutCreator. WebAppShortcutCreator(const base::FilePath& app_data_dir, - const ShortcutInfo& shortcut_info, + const ShortcutInfo* shortcut_info, const extensions::FileHandlersInfo& file_handlers_info); virtual ~WebAppShortcutCreator(); @@ -117,8 +120,8 @@ // ~/Library/Application Support/Chromium/Default/Web Applications/_crx_abc/ base::FilePath app_data_dir_; - // Information about the app. - ShortcutInfo info_; + // Information about the app. Owned by the caller of the constructor. + const ShortcutInfo* info_; // The app's file handlers. extensions::FileHandlersInfo file_handlers_info_;
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm index 5c04775..6c80590 100644 --- a/chrome/browser/web_applications/web_app_mac.mm +++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -219,10 +219,10 @@ true /* case_sensitive */); } -void LaunchShimOnFileThread(const web_app::ShortcutInfo& shortcut_info, +void LaunchShimOnFileThread(scoped_ptr<web_app::ShortcutInfo> shortcut_info, bool launched_after_rebuild) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - base::FilePath shim_path = web_app::GetAppInstallPath(shortcut_info); + base::FilePath shim_path = web_app::GetAppInstallPath(*shortcut_info); if (shim_path.empty() || !base::PathExists(shim_path) || @@ -230,7 +230,7 @@ // The user may have deleted the copy in the Applications folder, use the // one in the web app's |app_data_dir_|. base::FilePath app_data_dir = web_app::GetWebAppDataDirectory( - shortcut_info.profile_path, shortcut_info.extension_id, GURL()); + shortcut_info->profile_path, shortcut_info->extension_id, GURL()); shim_path = app_data_dir.Append(shim_path.BaseName()); } @@ -253,29 +253,44 @@ base::mac::NSToCFCast(@"app_mode_loader.app")); } -void UpdateAndLaunchShimOnFileThread( +void UpdatePlatformShortcutsInternal( + const base::FilePath& app_data_path, + const base::string16& old_app_title, const web_app::ShortcutInfo& shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + if (AppShimsDisabledForTest() && + !g_app_shims_allow_update_and_launch_in_tests) { + return; + } + + web_app::WebAppShortcutCreator shortcut_creator(app_data_path, &shortcut_info, + file_handlers_info); + shortcut_creator.UpdateShortcuts(); +} + +void UpdateAndLaunchShimOnFileThread( + scoped_ptr<web_app::ShortcutInfo> shortcut_info, + const extensions::FileHandlersInfo& file_handlers_info) { base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( - shortcut_info.profile_path, shortcut_info.extension_id, GURL()); - web_app::internals::UpdatePlatformShortcuts( - shortcut_data_dir, base::string16(), shortcut_info, file_handlers_info); - LaunchShimOnFileThread(shortcut_info, true); + shortcut_info->profile_path, shortcut_info->extension_id, GURL()); + UpdatePlatformShortcutsInternal(shortcut_data_dir, base::string16(), + *shortcut_info, file_handlers_info); + LaunchShimOnFileThread(shortcut_info.Pass(), true); } void UpdateAndLaunchShim( - const web_app::ShortcutInfo& shortcut_info, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind( - &UpdateAndLaunchShimOnFileThread, shortcut_info, file_handlers_info)); + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&UpdateAndLaunchShimOnFileThread, base::Passed(&shortcut_info), + file_handlers_info)); } -void RebuildAppAndLaunch(const web_app::ShortcutInfo& shortcut_info) { +void RebuildAppAndLaunch(scoped_ptr<web_app::ShortcutInfo> shortcut_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (shortcut_info.extension_id == app_mode::kAppListModeId) { + if (shortcut_info->extension_id == app_mode::kAppListModeId) { AppListService* app_list_service = AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE); app_list_service->CreateShortcut(); @@ -285,14 +300,14 @@ ProfileManager* profile_manager = g_browser_process->profile_manager(); Profile* profile = - profile_manager->GetProfileByPath(shortcut_info.profile_path); + profile_manager->GetProfileByPath(shortcut_info->profile_path); if (!profile || !profile_manager->IsValidProfile(profile)) return; extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile); const extensions::Extension* extension = registry->GetExtensionById( - shortcut_info.extension_id, extensions::ExtensionRegistry::ENABLED); + shortcut_info->extension_id, extensions::ExtensionRegistry::ENABLED); if (!extension || !extension->is_platform_app()) return; @@ -468,19 +483,19 @@ return bundle_paths; } -web_app::ShortcutInfo BuildShortcutInfoFromBundle( +scoped_ptr<web_app::ShortcutInfo> BuildShortcutInfoFromBundle( const base::FilePath& bundle_path) { NSDictionary* plist = ReadPlist(GetPlistPath(bundle_path)); - web_app::ShortcutInfo shortcut_info; - shortcut_info.extension_id = base::SysNSStringToUTF8( + scoped_ptr<web_app::ShortcutInfo> shortcut_info(new web_app::ShortcutInfo); + shortcut_info->extension_id = base::SysNSStringToUTF8( [plist valueForKey:app_mode::kCrAppModeShortcutIDKey]); - shortcut_info.is_platform_app = true; - shortcut_info.url = GURL(base::SysNSStringToUTF8( + shortcut_info->is_platform_app = true; + shortcut_info->url = GURL(base::SysNSStringToUTF8( [plist valueForKey:app_mode::kCrAppModeShortcutURLKey])); - shortcut_info.title = base::SysNSStringToUTF16( + shortcut_info->title = base::SysNSStringToUTF16( [plist valueForKey:app_mode::kCrAppModeShortcutNameKey]); - shortcut_info.profile_name = base::SysNSStringToUTF8( + shortcut_info->profile_name = base::SysNSStringToUTF8( [plist valueForKey:app_mode::kCrAppModeProfileNameKey]); // Figure out the profile_path. Since the user_data_dir could contain the @@ -490,14 +505,14 @@ base::FilePath profile_base_name = base::mac::NSStringToFilePath( [plist valueForKey:app_mode::kCrAppModeProfileDirKey]); if (user_data_dir.DirName().DirName().BaseName() == profile_base_name) - shortcut_info.profile_path = user_data_dir.DirName().DirName(); + shortcut_info->profile_path = user_data_dir.DirName().DirName(); else - shortcut_info.profile_path = user_data_dir.Append(profile_base_name); + shortcut_info->profile_path = user_data_dir.Append(profile_base_name); return shortcut_info; } -web_app::ShortcutInfo RecordAppShimErrorAndBuildShortcutInfo( +scoped_ptr<web_app::ShortcutInfo> RecordAppShimErrorAndBuildShortcutInfo( const base::FilePath& bundle_path) { NSDictionary* plist = ReadPlist(GetPlistPath(bundle_path)); NSString* version_string = [plist valueForKey:app_mode::kCrBundleVersionKey]; @@ -559,10 +574,10 @@ } void RevealAppShimInFinderForAppOnFileThread( - const web_app::ShortcutInfo& shortcut_info, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, const base::FilePath& app_path) { web_app::WebAppShortcutCreator shortcut_creator( - app_path, shortcut_info, extensions::FileHandlersInfo()); + app_path, shortcut_info.get(), extensions::FileHandlersInfo()); shortcut_creator.RevealAppShimInFinder(); } @@ -616,11 +631,13 @@ WebAppShortcutCreator::WebAppShortcutCreator( const base::FilePath& app_data_dir, - const ShortcutInfo& shortcut_info, + const ShortcutInfo* shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) : app_data_dir_(app_data_dir), info_(shortcut_info), - file_handlers_info_(file_handlers_info) {} + file_handlers_info_(file_handlers_info) { + DCHECK(shortcut_info); +} WebAppShortcutCreator::~WebAppShortcutCreator() {} @@ -639,11 +656,11 @@ // Check if there should be a separate shortcut made for different profiles. // Such shortcuts will have a |profile_name| set on the ShortcutInfo, // otherwise it will be empty. - if (!info_.profile_name.empty()) { - app_name += info_.profile_path.BaseName().value(); + if (!info_->profile_name.empty()) { + app_name += info_->profile_path.BaseName().value(); app_name += ' '; } - app_name += info_.extension_id; + app_name += info_->extension_id; return base::FilePath(app_name).ReplaceExtension("app"); } @@ -721,7 +738,7 @@ // placed under the profile path. For shims, this copy is used when the // version under Applications is removed, and not needed for app list because // setting LSUIElement means there is no Dock "running" status to show. - const bool is_app_list = info_.extension_id == app_mode::kAppListModeId; + const bool is_app_list = info_->extension_id == app_mode::kAppListModeId; if (is_app_list) { path_to_add_to_dock = base::SysUTF8ToNSString( applications_dir.Append(GetShortcutBasename()).AsUTF8Unsafe()); @@ -812,9 +829,9 @@ } bool WebAppShortcutCreator::UpdatePlist(const base::FilePath& app_path) const { - NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id); - NSString* extension_title = base::SysUTF16ToNSString(info_.title); - NSString* extension_url = base::SysUTF8ToNSString(info_.url.spec()); + NSString* extension_id = base::SysUTF8ToNSString(info_->extension_id); + NSString* extension_title = base::SysUTF16ToNSString(info_->title); + NSString* extension_url = base::SysUTF8ToNSString(info_->url.spec()); NSString* chrome_bundle_id = base::SysUTF8ToNSString(base::mac::BaseBundleID()); NSDictionary* replacement_dict = @@ -847,19 +864,19 @@ // 2. Fill in other values. [plist setObject:base::SysUTF8ToNSString(chrome::VersionInfo().Version()) forKey:app_mode::kCrBundleVersionKey]; - [plist setObject:base::SysUTF8ToNSString(info_.version_for_display) + [plist setObject:base::SysUTF8ToNSString(info_->version_for_display) forKey:app_mode::kCFBundleShortVersionStringKey]; [plist setObject:base::SysUTF8ToNSString(GetBundleIdentifier()) forKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]; [plist setObject:base::mac::FilePathToNSString(app_data_dir_) forKey:app_mode::kCrAppModeUserDataDirKey]; - [plist setObject:base::mac::FilePathToNSString(info_.profile_path.BaseName()) + [plist setObject:base::mac::FilePathToNSString(info_->profile_path.BaseName()) forKey:app_mode::kCrAppModeProfileDirKey]; - [plist setObject:base::SysUTF8ToNSString(info_.profile_name) + [plist setObject:base::SysUTF8ToNSString(info_->profile_name) forKey:app_mode::kCrAppModeProfileNameKey]; [plist setObject:[NSNumber numberWithBool:YES] forKey:app_mode::kLSHasLocalizedDisplayNameKey]; - if (info_.extension_id == app_mode::kAppListModeId) { + if (info_->extension_id == app_mode::kAppListModeId) { // Prevent the app list from bouncing in the dock, and getting a run light. [plist setObject:[NSNumber numberWithBool:YES] forKey:kLSUIElement]; @@ -886,14 +903,13 @@ if (!base::CreateDirectory(localized_dir)) return false; - NSString* bundle_name = base::SysUTF16ToNSString(info_.title); - NSString* display_name = base::SysUTF16ToNSString(info_.title); - if (HasExistingExtensionShim(GetApplicationsDirname(), - info_.extension_id, + NSString* bundle_name = base::SysUTF16ToNSString(info_->title); + NSString* display_name = base::SysUTF16ToNSString(info_->title); + if (HasExistingExtensionShim(GetApplicationsDirname(), info_->extension_id, app_path.BaseName())) { display_name = [bundle_name stringByAppendingString:base::SysUTF8ToNSString( - " (" + info_.profile_name + ")")]; + " (" + info_->profile_name + ")")]; } NSDictionary* strings_plist = @{ @@ -908,13 +924,13 @@ } bool WebAppShortcutCreator::UpdateIcon(const base::FilePath& app_path) const { - if (info_.favicon.empty()) + if (info_->favicon.empty()) return true; ScopedCarbonHandle icon_family(0); bool image_added = false; - for (gfx::ImageFamily::const_iterator it = info_.favicon.begin(); - it != info_.favicon.end(); ++it) { + for (gfx::ImageFamily::const_iterator it = info_->favicon.begin(); + it != info_->favicon.end(); ++it) { if (it->IsEmpty()) continue; @@ -964,13 +980,12 @@ std::string WebAppShortcutCreator::GetBundleIdentifier() const { // Replace spaces in the profile path with hyphen. std::string normalized_profile_path; - base::ReplaceChars(info_.profile_path.BaseName().value(), - " ", "-", &normalized_profile_path); + base::ReplaceChars(info_->profile_path.BaseName().value(), " ", "-", + &normalized_profile_path); // This matches APP_MODE_APP_BUNDLE_ID in chrome/chrome.gyp. - std::string bundle_id = - base::mac::BaseBundleID() + std::string(".app.") + - normalized_profile_path + "-" + info_.extension_id; + std::string bundle_id = base::mac::BaseBundleID() + std::string(".app.") + + normalized_profile_path + "-" + info_->extension_id; return bundle_id; } @@ -1006,21 +1021,20 @@ } base::FilePath GetAppInstallPath(const ShortcutInfo& shortcut_info) { - WebAppShortcutCreator shortcut_creator( - base::FilePath(), shortcut_info, extensions::FileHandlersInfo()); + WebAppShortcutCreator shortcut_creator(base::FilePath(), &shortcut_info, + extensions::FileHandlersInfo()); return shortcut_creator.GetApplicationsShortcutPath(); } -void MaybeLaunchShortcut(const ShortcutInfo& shortcut_info) { +void MaybeLaunchShortcut(scoped_ptr<ShortcutInfo> shortcut_info) { if (AppShimsDisabledForTest() && !g_app_shims_allow_update_and_launch_in_tests) { return; } content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&LaunchShimOnFileThread, shortcut_info, false)); + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&LaunchShimOnFileThread, base::Passed(&shortcut_info), false)); } bool MaybeRebuildShortcut(const base::CommandLine& command_line) { @@ -1042,7 +1056,7 @@ Profile* profile, const extensions::Extension* app, const base::Callback<void(bool)>& close_callback, - const ShortcutInfo& shortcut_info) { + scoped_ptr<ShortcutInfo> shortcut_info) { base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]); NSButton* continue_button = [alert @@ -1074,7 +1088,7 @@ const int kIconPreviewSizePixels = 128; const int kIconPreviewTargetSize = 64; - const gfx::Image* icon = shortcut_info.favicon.GetBest( + const gfx::Image* icon = shortcut_info->favicon.GetBest( kIconPreviewSizePixels, kIconPreviewSizePixels); if (icon && !icon->IsEmpty()) { @@ -1123,19 +1137,19 @@ void RevealAppShimInFinderForApp(Profile* profile, const extensions::Extension* app) { - const web_app::ShortcutInfo shortcut_info = + scoped_ptr<web_app::ShortcutInfo> shortcut_info = ShortcutInfoForExtensionAndProfile(app, profile); content::BrowserThread::PostTask( content::BrowserThread::FILE, FROM_HERE, - base::Bind(&RevealAppShimInFinderForAppOnFileThread, shortcut_info, - app->path())); + base::Bind(&RevealAppShimInFinderForAppOnFileThread, + base::Passed(&shortcut_info), app->path())); } namespace internals { bool CreatePlatformShortcuts( const base::FilePath& app_data_path, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info, const ShortcutLocations& creation_locations, ShortcutCreationReason creation_reason) { @@ -1143,33 +1157,26 @@ if (AppShimsDisabledForTest()) return true; - WebAppShortcutCreator shortcut_creator( - app_data_path, shortcut_info, file_handlers_info); + WebAppShortcutCreator shortcut_creator(app_data_path, shortcut_info.get(), + file_handlers_info); return shortcut_creator.CreateShortcuts(creation_reason, creation_locations); } void DeletePlatformShortcuts(const base::FilePath& app_data_path, - const ShortcutInfo& shortcut_info) { + scoped_ptr<ShortcutInfo> shortcut_info) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - WebAppShortcutCreator shortcut_creator( - app_data_path, shortcut_info, extensions::FileHandlersInfo()); + WebAppShortcutCreator shortcut_creator(app_data_path, shortcut_info.get(), + extensions::FileHandlersInfo()); shortcut_creator.DeleteShortcuts(); } void UpdatePlatformShortcuts( const base::FilePath& app_data_path, const base::string16& old_app_title, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - if (AppShimsDisabledForTest() && - !g_app_shims_allow_update_and_launch_in_tests) { - return; - } - - WebAppShortcutCreator shortcut_creator( - app_data_path, shortcut_info, file_handlers_info); - shortcut_creator.UpdateShortcuts(); + UpdatePlatformShortcutsInternal(app_data_path, old_app_title, *shortcut_info, + file_handlers_info); } void DeleteAllShortcutsForProfile(const base::FilePath& profile_path) { @@ -1179,10 +1186,10 @@ for (std::vector<base::FilePath>::const_iterator it = bundles.begin(); it != bundles.end(); ++it) { - web_app::ShortcutInfo shortcut_info = + scoped_ptr<web_app::ShortcutInfo> shortcut_info = BuildShortcutInfoFromBundle(*it); - WebAppShortcutCreator shortcut_creator( - it->DirName(), shortcut_info, extensions::FileHandlersInfo()); + WebAppShortcutCreator shortcut_creator(it->DirName(), shortcut_info.get(), + extensions::FileHandlersInfo()); shortcut_creator.DeleteShortcuts(); } }
diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm index 3b7fa4d..499ac56 100644 --- a/chrome/browser/web_applications/web_app_mac_unittest.mm +++ b/chrome/browser/web_applications/web_app_mac_unittest.mm
@@ -13,6 +13,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/mac/foundation_util.h" #include "base/mac/scoped_nsobject.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -39,14 +40,14 @@ class WebAppShortcutCreatorMock : public web_app::WebAppShortcutCreator { public: WebAppShortcutCreatorMock(const base::FilePath& app_data_dir, - const web_app::ShortcutInfo& shortcut_info) + const web_app::ShortcutInfo* shortcut_info) : WebAppShortcutCreator(app_data_dir, shortcut_info, extensions::FileHandlersInfo()) {} WebAppShortcutCreatorMock( const base::FilePath& app_data_dir, - const web_app::ShortcutInfo& shortcut_info, + const web_app::ShortcutInfo* shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) : WebAppShortcutCreator(app_data_dir, shortcut_info, file_handlers_info) { } @@ -60,15 +61,15 @@ DISALLOW_COPY_AND_ASSIGN(WebAppShortcutCreatorMock); }; -web_app::ShortcutInfo GetShortcutInfo() { - web_app::ShortcutInfo info; - info.extension_id = "extensionid"; - info.extension_path = base::FilePath("/fake/extension/path"); - info.title = base::ASCIIToUTF16("Shortcut Title"); - info.url = GURL("http://example.com/"); - info.profile_path = base::FilePath("user_data_dir").Append("Profile 1"); - info.profile_name = "profile name"; - info.version_for_display = "stable 1.0"; +scoped_ptr<web_app::ShortcutInfo> GetShortcutInfo() { + scoped_ptr<web_app::ShortcutInfo> info(new web_app::ShortcutInfo); + info->extension_id = "extensionid"; + info->extension_path = base::FilePath("/fake/extension/path"); + info->title = base::ASCIIToUTF16("Shortcut Title"); + info->url = GURL("http://example.com/"); + info->profile_path = base::FilePath("user_data_dir").Append("Profile 1"); + info->profile_name = "profile name"; + info->version_for_display = "stable 1.0"; return info; } @@ -85,9 +86,8 @@ destination_dir_ = temp_destination_dir_.path(); info_ = GetShortcutInfo(); - shim_base_name_ = base::FilePath( - info_.profile_path.BaseName().value() + - " " + info_.extension_id + ".app"); + shim_base_name_ = base::FilePath(info_->profile_path.BaseName().value() + + " " + info_->extension_id + ".app"); internal_shim_path_ = app_data_dir_.Append(shim_base_name_); shim_path_ = destination_dir_.Append(shim_base_name_); } @@ -97,7 +97,7 @@ base::FilePath app_data_dir_; base::FilePath destination_dir_; - web_app::ShortcutInfo info_; + scoped_ptr<web_app::ShortcutInfo> info_; base::FilePath shim_base_name_; base::FilePath internal_shim_path_; base::FilePath shim_path_; @@ -112,7 +112,8 @@ namespace web_app { TEST_F(WebAppShortcutCreatorTest, CreateShortcuts) { - NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, info_); + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, + info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); @@ -126,16 +127,16 @@ shim_path_.Append("Contents").Append("Info.plist"); NSDictionary* plist = [NSDictionary dictionaryWithContentsOfFile: base::mac::FilePathToNSString(plist_path)]; - EXPECT_NSEQ(base::SysUTF8ToNSString(info_.extension_id), + EXPECT_NSEQ(base::SysUTF8ToNSString(info_->extension_id), [plist objectForKey:app_mode::kCrAppModeShortcutIDKey]); - EXPECT_NSEQ(base::SysUTF16ToNSString(info_.title), + EXPECT_NSEQ(base::SysUTF16ToNSString(info_->title), [plist objectForKey:app_mode::kCrAppModeShortcutNameKey]); - EXPECT_NSEQ(base::SysUTF8ToNSString(info_.url.spec()), + EXPECT_NSEQ(base::SysUTF8ToNSString(info_->url.spec()), [plist objectForKey:app_mode::kCrAppModeShortcutURLKey]); EXPECT_NSEQ(base::SysUTF8ToNSString(chrome::VersionInfo().Version()), [plist objectForKey:app_mode::kCrBundleVersionKey]); - EXPECT_NSEQ(base::SysUTF8ToNSString(info_.version_for_display), + EXPECT_NSEQ(base::SysUTF8ToNSString(info_->version_for_display), [plist objectForKey:app_mode::kCFBundleShortVersionStringKey]); // Make sure all values in the plist are actually filled in. @@ -155,12 +156,13 @@ base::FilePath other_folder = other_folder_temp_dir.path(); base::FilePath other_shim_path = other_folder.Append(shim_base_name_); - NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, info_); + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, + info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); std::string expected_bundle_id = kFakeChromeBundleId; - expected_bundle_id += ".app.Profile-1-" + info_.extension_id; + expected_bundle_id += ".app.Profile-1-" + info_->extension_id; EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id)) .WillOnce(Return(other_shim_path)); @@ -196,12 +198,13 @@ base::FilePath other_folder = other_folder_temp_dir.path(); base::FilePath other_shim_path = other_folder.Append(shim_base_name_); - NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, info_); + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, + info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); std::string expected_bundle_id = kFakeChromeBundleId; - expected_bundle_id += ".app.Profile-1-" + info_.extension_id; + expected_bundle_id += ".app.Profile-1-" + info_->extension_id; EXPECT_CALL(shortcut_creator, GetAppBundleById(expected_bundle_id)) .WillOnce(Return(other_shim_path)); @@ -236,18 +239,20 @@ TEST_F(WebAppShortcutCreatorTest, CreateAppListShortcut) { // With an empty |profile_name|, the shortcut path should not have the profile // directory prepended to the extension id on the app bundle name. - info_.profile_name.clear(); + info_->profile_name.clear(); base::FilePath dst_path = - destination_dir_.Append(info_.extension_id + ".app"); + destination_dir_.Append(info_->extension_id + ".app"); - NiceMock<WebAppShortcutCreatorMock> shortcut_creator(base::FilePath(), info_); + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(base::FilePath(), + info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); EXPECT_EQ(dst_path.BaseName(), shortcut_creator.GetShortcutBasename()); } TEST_F(WebAppShortcutCreatorTest, RunShortcut) { - NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, info_); + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, + info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); @@ -265,7 +270,8 @@ base::FilePath non_existent_path = destination_dir_.Append("not-existent").Append("name.app"); - NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, info_); + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(app_data_dir_, + info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(non_existent_path)); EXPECT_FALSE(shortcut_creator.CreateShortcuts( @@ -276,8 +282,8 @@ gfx::Image product_logo = ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed( IDR_PRODUCT_LOGO_32); - info_.favicon.Add(product_logo); - WebAppShortcutCreatorMock shortcut_creator(app_data_dir_, info_); + info_->favicon.Add(product_logo); + WebAppShortcutCreatorMock shortcut_creator(app_data_dir_, info_.get()); ASSERT_TRUE(shortcut_creator.UpdateIcon(shim_path_)); base::FilePath icon_path = @@ -291,7 +297,7 @@ } TEST_F(WebAppShortcutCreatorTest, RevealAppShimInFinder) { - WebAppShortcutCreatorMock shortcut_creator(app_data_dir_, info_); + WebAppShortcutCreatorMock shortcut_creator(app_data_dir_, info_.get()); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); @@ -321,7 +327,7 @@ file_handlers_info.push_back(handler_1); NiceMock<WebAppShortcutCreatorMock> shortcut_creator( - app_data_dir_, info_, file_handlers_info); + app_data_dir_, info_.get(), file_handlers_info); EXPECT_CALL(shortcut_creator, GetApplicationsDirname()) .WillRepeatedly(Return(destination_dir_)); EXPECT_TRUE(shortcut_creator.CreateShortcuts(
diff --git a/chrome/browser/web_applications/web_app_unittest.cc b/chrome/browser/web_applications/web_app_unittest.cc index 13359e7..f9cac1e 100644 --- a/chrome/browser/web_applications/web_app_unittest.cc +++ b/chrome/browser/web_applications/web_app_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/web_applications/web_app.h" #include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/web_applications/web_app.h" @@ -43,12 +44,12 @@ RenderViewHostTester::TestOnMessageReceived( rvh(), ChromeViewHostMsg_DidGetWebApplicationInfo(0, web_app_info)); - web_app::ShortcutInfo info; - web_app::GetShortcutInfoForTab(web_contents(), &info); + scoped_ptr<web_app::ShortcutInfo> info = + web_app::GetShortcutInfoForTab(web_contents()); - EXPECT_EQ(title, info.title); - EXPECT_EQ(description, info.description); - EXPECT_EQ(url, info.url); + EXPECT_EQ(title, info->title); + EXPECT_EQ(description, info->description); + EXPECT_EQ(url, info->url); } #endif
diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc index 45fdf5e9..2630c61 100644 --- a/chrome/browser/web_applications/web_app_win.cc +++ b/chrome/browser/web_applications/web_app_win.cc
@@ -11,6 +11,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/md5.h" +#include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/strings/string16.h" #include "base/strings/string_piece.h" @@ -334,16 +335,16 @@ } } -void CreateIconAndSetRelaunchDetails(const base::FilePath& web_app_path, - const base::FilePath& icon_file, - const web_app::ShortcutInfo& shortcut_info, - HWND hwnd) { +void CreateIconAndSetRelaunchDetails( + const base::FilePath& web_app_path, + const base::FilePath& icon_file, + scoped_ptr<web_app::ShortcutInfo> shortcut_info, + HWND hwnd) { DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); - base::CommandLine command_line = - ShellIntegration::CommandLineArgsForLauncher(shortcut_info.url, - shortcut_info.extension_id, - shortcut_info.profile_path); + base::CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher( + shortcut_info->url, shortcut_info->extension_id, + shortcut_info->profile_path); base::FilePath chrome_exe; if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { @@ -351,36 +352,31 @@ return; } command_line.SetProgram(chrome_exe); - ui::win::SetRelaunchDetailsForWindow( - command_line.GetCommandLineString(), shortcut_info.title, hwnd); + ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(), + shortcut_info->title, hwnd); if (!base::PathExists(web_app_path) && !base::CreateDirectory(web_app_path)) return; ui::win::SetAppIconForWindow(icon_file.value(), hwnd); - web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon, true); + web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info->favicon, true); } void OnShortcutInfoLoadedForSetRelaunchDetails( HWND hwnd, - const web_app::ShortcutInfo& shortcut_info) { + scoped_ptr<web_app::ShortcutInfo> shortcut_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Set window's icon to the one we're about to create/update in the web app // path. The icon cache will refresh on icon creation. - base::FilePath web_app_path = - web_app::GetWebAppDataDirectory(shortcut_info.profile_path, - shortcut_info.extension_id, - shortcut_info.url); + base::FilePath web_app_path = web_app::GetWebAppDataDirectory( + shortcut_info->profile_path, shortcut_info->extension_id, + shortcut_info->url); base::FilePath icon_file = - web_app::internals::GetIconFilePath(web_app_path, shortcut_info.title); + web_app::internals::GetIconFilePath(web_app_path, shortcut_info->title); content::BrowserThread::PostBlockingPoolTask( - FROM_HERE, - base::Bind(&CreateIconAndSetRelaunchDetails, - web_app_path, - icon_file, - shortcut_info, - hwnd)); + FROM_HERE, base::Bind(&CreateIconAndSetRelaunchDetails, web_app_path, + icon_file, base::Passed(&shortcut_info), hwnd)); } // Creates an "app shim exe" by linking or copying the generic app shim exe. @@ -525,26 +521,24 @@ namespace web_app { -base::FilePath CreateShortcutInWebAppDir(const base::FilePath& web_app_dir, - const ShortcutInfo& shortcut_info) { +base::FilePath CreateShortcutInWebAppDir( + const base::FilePath& web_app_dir, + scoped_ptr<ShortcutInfo> shortcut_info) { std::vector<base::FilePath> paths; paths.push_back(web_app_dir); std::vector<base::FilePath> out_filenames; base::FilePath web_app_dir_shortcut = - web_app_dir.Append(internals::GetSanitizedFileName(shortcut_info.title)) + web_app_dir.Append(internals::GetSanitizedFileName(shortcut_info->title)) .AddExtension(installer::kLnkExt); if (!PathExists(web_app_dir_shortcut)) { - CreateShortcutsInPaths(web_app_dir, - shortcut_info, - paths, - SHORTCUT_CREATION_BY_USER, - &out_filenames); + CreateShortcutsInPaths(web_app_dir, *shortcut_info, paths, + SHORTCUT_CREATION_BY_USER, &out_filenames); DCHECK_EQ(out_filenames.size(), 1u); DCHECK_EQ(out_filenames[0].value(), web_app_dir_shortcut.value()); } else { internals::CheckAndSaveIcon( - internals::GetIconFilePath(web_app_dir, shortcut_info.title), - shortcut_info.favicon, true); + internals::GetIconFilePath(web_app_dir, shortcut_info->title), + shortcut_info->favicon, true); } return web_app_dir_shortcut; } @@ -586,7 +580,7 @@ bool CreatePlatformShortcuts( const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info, const ShortcutLocations& creation_locations, ShortcutCreationReason creation_reason) { @@ -613,12 +607,12 @@ if (shortcut_paths.empty()) return false; - if (!CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths, + if (!CreateShortcutsInPaths(web_app_path, *shortcut_info, shortcut_paths, creation_reason, NULL)) return false; if (pin_to_taskbar) { - base::FilePath file_name = GetSanitizedFileName(shortcut_info.title); + base::FilePath file_name = GetSanitizedFileName(shortcut_info->title); // Use the web app path shortcut for pinning to avoid having unique numbers // in the application name. base::FilePath shortcut_to_pin = web_app_path.Append(file_name). @@ -630,8 +624,8 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableAppsFileAssociations)) { CreateFileAssociationsForApp( - shortcut_info.extension_id, shortcut_info.title, - shortcut_info.profile_path, file_handlers_info); + shortcut_info->extension_id, shortcut_info->title, + shortcut_info->profile_path, file_handlers_info); } return true; @@ -640,30 +634,30 @@ void UpdatePlatformShortcuts( const base::FilePath& web_app_path, const base::string16& old_app_title, - const ShortcutInfo& shortcut_info, + scoped_ptr<ShortcutInfo> shortcut_info, const extensions::FileHandlersInfo& file_handlers_info) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); // Generates file name to use with persisted ico and shortcut file. base::FilePath file_name = - web_app::internals::GetSanitizedFileName(shortcut_info.title); + web_app::internals::GetSanitizedFileName(shortcut_info->title); - if (old_app_title != shortcut_info.title) { + if (old_app_title != shortcut_info->title) { // The app's title has changed. Delete all existing app shortcuts and // recreate them in any locations they already existed (but do not add them // to locations where they do not currently exist). bool was_pinned_to_taskbar; std::vector<base::FilePath> shortcut_paths; GetShortcutLocationsAndDeleteShortcuts( - web_app_path, shortcut_info.profile_path, old_app_title, + web_app_path, shortcut_info->profile_path, old_app_title, &was_pinned_to_taskbar, &shortcut_paths); - CreateShortcutsInPaths(web_app_path, shortcut_info, shortcut_paths, + CreateShortcutsInPaths(web_app_path, *shortcut_info, shortcut_paths, SHORTCUT_CREATION_BY_USER, NULL); // If the shortcut was pinned to the taskbar, // GetShortcutLocationsAndDeleteShortcuts will have deleted it. In that // case, re-pin it. if (was_pinned_to_taskbar) { - base::FilePath file_name = GetSanitizedFileName(shortcut_info.title); + base::FilePath file_name = GetSanitizedFileName(shortcut_info->title); // Use the web app path shortcut for pinning to avoid having unique // numbers in the application name. base::FilePath shortcut_to_pin = web_app_path.Append(file_name). @@ -673,15 +667,16 @@ } // Update the icon if necessary. - base::FilePath icon_file = GetIconFilePath(web_app_path, shortcut_info.title); - CheckAndSaveIcon(icon_file, shortcut_info.favicon, true); + base::FilePath icon_file = + GetIconFilePath(web_app_path, shortcut_info->title); + CheckAndSaveIcon(icon_file, shortcut_info->favicon, true); } void DeletePlatformShortcuts(const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info) { - GetShortcutLocationsAndDeleteShortcuts( - web_app_path, shortcut_info.profile_path, shortcut_info.title, NULL, - NULL); + scoped_ptr<ShortcutInfo> shortcut_info) { + GetShortcutLocationsAndDeleteShortcuts(web_app_path, + shortcut_info->profile_path, + shortcut_info->title, NULL, NULL); // If there are no more shortcuts in the Chrome Apps subdirectory, remove it. base::FilePath chrome_apps_dir;
diff --git a/chrome/browser/web_applications/web_app_win.h b/chrome/browser/web_applications/web_app_win.h index 7dba046..08bb704 100644 --- a/chrome/browser/web_applications/web_app_win.h +++ b/chrome/browser/web_applications/web_app_win.h
@@ -26,8 +26,9 @@ // Create a shortcut in the given web app data dir, returning the name of the // created shortcut. -base::FilePath CreateShortcutInWebAppDir(const base::FilePath& web_app_path, - const ShortcutInfo& shortcut_info); +base::FilePath CreateShortcutInWebAppDir( + const base::FilePath& web_app_path, + scoped_ptr<ShortcutInfo> shortcut_info); // Update the relaunch details for the given app's window, making the taskbar // group's "Pin to the taskbar" button function correctly.
diff --git a/chrome/browser_tests.isolate b/chrome/browser_tests.isolate index 7d97d28..89f84393 100644 --- a/chrome/browser_tests.isolate +++ b/chrome/browser_tests.isolate
@@ -41,6 +41,14 @@ ], }, }], + ['OS=="linux" and branding=="Chrome" and enable_pepper_cdms==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/libwidevinecdm.so', + '<(PRODUCT_DIR)/libwidevinecdmadapter.so', + ], + }, + }], ['OS=="linux" and libpeer_target_type=="loadable_module"', { 'variables': { 'files': [ @@ -182,6 +190,14 @@ ], }, }], + ['OS=="mac" and branding=="Chrome" and enable_pepper_cdms==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/libwidevinecdm.dylib', + '<(PRODUCT_DIR)/widevinecdmadapter.plugin', + ], + }, + }], ['OS=="win"', { 'variables': { 'files': [ @@ -195,6 +211,14 @@ ], }, }], + ['OS=="win" and branding=="Chrome" and enable_pepper_cdms==1', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/widevinecdm.dll', + '<(PRODUCT_DIR)/widevinecdmadapter.dll', + ], + }, + }], ['OS=="win" and target_arch=="ia32"', { 'variables': { 'files': [
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a8a5f9b..48402cf 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -539,6 +539,8 @@ 'browser/memory_details_linux.cc', 'browser/memory_details_mac.cc', 'browser/memory_details_win.cc', + 'browser/mod_pagespeed/mod_pagespeed_metrics.cc', + 'browser/mod_pagespeed/mod_pagespeed_metrics.h', 'browser/native_window_notification_source.h', 'browser/net/predictor_tab_helper.cc', 'browser/net/predictor_tab_helper.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index e89e46d..31d7ff0 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -440,7 +440,6 @@ 'browser/ui/autofill/test_generated_credit_card_bubble_view.h', 'browser/ui/blocked_content/popup_blocker_browsertest.cc', 'browser/ui/bookmarks/bookmark_browsertest.cc', - 'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc', 'browser/ui/browser_browsertest.cc', 'browser/ui/browser_close_browsertest.cc', 'browser/ui/browser_command_controller_browsertest.cc', @@ -604,6 +603,7 @@ 'browser/ui/views/autofill/card_unmask_prompt_view_tester_views.h', 'browser/ui/views/autofill/password_generation_popup_view_tester_views.cc', 'browser/ui/views/autofill/password_generation_popup_view_tester_views.h', + 'browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc', 'browser/ui/views/collected_cookies_views_browsertest.cc', 'browser/ui/views/extensions/bookmark_override_browsertest.cc', 'browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc', @@ -725,6 +725,7 @@ 'browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc', 'browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.cc', 'browser/chromeos/login/users/wallpaper/wallpaper_manager_test_utils.h', + 'browser/chromeos/login/webview_login_browsertest.cc', 'browser/chromeos/login/wizard_controller_browsertest.cc', 'browser/chromeos/memory/oom_priority_manager_browsertest.cc', 'browser/chromeos/net/network_portal_detector_impl_browsertest.cc', @@ -735,6 +736,9 @@ 'browser/chromeos/policy/device_policy_cros_browser_test.h', 'browser/chromeos/policy/device_status_collector_browsertest.cc', 'browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc', + 'browser/chromeos/policy/force_maximize_on_first_run_chromeos_browsertest.cc', + 'browser/chromeos/policy/login_policy_test_base.cc', + 'browser/chromeos/policy/login_policy_test_base.h', 'browser/chromeos/policy/login_screen_default_policy_browsertest.cc', 'browser/chromeos/policy/policy_cert_verifier_browsertest.cc', 'browser/chromeos/policy/power_policy_browsertest.cc', @@ -761,6 +765,7 @@ 'browser/policy/cloud/test_request_interceptor.h', 'browser/policy/policy_browsertest.cc', 'browser/policy/policy_prefs_browsertest.cc', + 'browser/policy/policy_startup_browsertest.cc', 'browser/ui/webui/options/certificate_manager_browsertest.cc', 'browser/ui/webui/options/preferences_browsertest.cc', 'browser/ui/webui/options/preferences_browsertest.h', @@ -2159,6 +2164,7 @@ '../apps/load_and_launch_browsertest.cc', 'browser/printing/cloud_print/test/cloud_print_policy_browsertest.cc', 'browser/printing/cloud_print/test/cloud_print_proxy_process_browsertest.cc', + 'browser/policy/policy_startup_browsertest.cc', # chromeos does not support profile list avatar menu 'browser/profiles/profile_list_desktop_browsertest.cc', 'browser/service_process/service_process_control_browsertest.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 5b3ba361..1d6305e 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -148,6 +148,7 @@ 'browser/metrics/variations/variations_request_scheduler_unittest.cc', 'browser/metrics/variations/variations_seed_store_unittest.cc', 'browser/metrics/variations/variations_service_unittest.cc', + 'browser/mod_pagespeed/mod_pagespeed_metrics_unittest.cc', 'browser/net/certificate_error_reporter_unittest.cc', 'browser/net/chrome_fraudulent_certificate_reporter_unittest.cc', 'browser/net/chrome_network_delegate_unittest.cc',
diff --git a/chrome/common/chrome_result_codes.h b/chrome/common/chrome_result_codes.h index c047b46c..9f80d9d1 100644 --- a/chrome/common/chrome_result_codes.h +++ b/chrome/common/chrome_result_codes.h
@@ -89,6 +89,9 @@ // (Linux-only). RESULT_CODE_SXS_MIGRATION_FAILED, + // The action is not allowed by a policy. + RESULT_CODE_ACTION_DISALLOWED_BY_POLICY, + // Last return code (keep this last). RESULT_CODE_CHROME_LAST_CODE, };
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl index 68fc3455..be6cd53 100644 --- a/chrome/common/extensions/api/file_manager_private.idl +++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -173,6 +173,20 @@ public }; +// Source of the volume data. +enum VolumeSource { + // Represents a mounted file. In most cases, simply an archive. + file, + + // Representing a device, eg. an MTP device. Also, used for Downloads as it's + // containing files stored on the Chrome OS device. + device, + + // Used for volumes which contain files on a remote machine, eg. Drive or + // cloud services implemented via the File System Provider API. + network +}; + // A file task represents an action that the file manager can perform over the // currently selected files. See // chrome/browser/chromeos/extensions/file_manager/file_tasks.h for details @@ -280,12 +294,15 @@ // ID of the disk volume. DOMString volumeId; - // Id the provided file system (for proviided file systems). + // Id the provided file system (for provided file systems). DOMString? fileSystemId; // Extension providing this volume (for provided file systems). DOMString? extensionId; + // Source of the volume data. + VolumeSource? volumeSource; + // Label of the volume (if available). DOMString? volumeLabel;
diff --git a/chrome/common/extensions/api/file_system_provider.idl b/chrome/common/extensions/api/file_system_provider.idl index 2854ae8..0b58961 100644 --- a/chrome/common/extensions/api/file_system_provider.idl +++ b/chrome/common/extensions/api/file_system_provider.idl
@@ -41,6 +41,22 @@ DELETED }; + // Source of the file system data. + enum FileSystemSource { + // The file system is handling a file, eg. an archive file obtained via the + // <code>OnLaunched</code> event and the <code>file_handlers</code> manifest + // entry. + FILE, + + // The file system contents are fetched from an external device, such as a + // USB device, but not via <code>file_handlers</code>. + DEVICE, + + // The file system is network based. The contents are obtained from another + // server or local network. Eg. cloud services. + NETWORK + }; + // Represents metadata of a file or a directory. dictionary EntryMetadata { // True if it is a directory. @@ -109,6 +125,9 @@ // List of currently opened files. OpenedFile[] openedFiles; + // Source of the file system data. + FileSystemSource? source; + // Whether the file system supports the <code>tag</code> field for observing // directories. [nodoc] boolean? supportsNotifyTag; @@ -134,6 +153,9 @@ // or 0, then not limited. long? openedFilesLimit; + // Source of the file system data. + FileSystemSource? source; + // Whether the file system supports the <code>tag</code> field for observed // directories. Required in order to enable the internal cache. [nodoc] boolean? supportsNotifyTag; @@ -451,6 +473,9 @@ // must be descriptive but doesn't have to be unique. The <code>fileSystemId // </code> must not be an empty string. // + // Depending on the type of the file system being mounted, the <code>source + // </code> option must be set appropriately. + // // In case of an error, <code>chrome.runtime.lastError</code> will be set // will a corresponding error code. static void mount(MountOptions options,
diff --git a/chrome/common/extensions/api/mdns.idl b/chrome/common/extensions/api/mdns.idl index f199d2f..53e9a32 100644 --- a/chrome/common/extensions/api/mdns.idl +++ b/chrome/common/extensions/api/mdns.idl
@@ -23,6 +23,13 @@ DOMString[] serviceData; }; + interface Properties { + // The maximum number of service instances that will be included in + // onServiceList events. If more instances are available, they may be + // truncated from the onServiceList event. + [value=64] static long MAX_SERVICE_INSTANCES_PER_EVENT(); + }; + interface Events { // Event fired to inform clients of the current complete set of known // available services. Clients should only need to store the list from the
diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml index 451eb3e..b68ad8c 100644 --- a/chrome/common/extensions/docs/server2/app.yaml +++ b/chrome/common/extensions/docs/server2/app.yaml
@@ -1,5 +1,5 @@ application: chrome-apps-doc -version: 3-48-2 +version: 3-49-0 runtime: python27 api_version: 1 threadsafe: false
diff --git a/chrome/common/extensions/docs/server2/cron.yaml b/chrome/common/extensions/docs/server2/cron.yaml index 504c11b..b72ccff 100644 --- a/chrome/common/extensions/docs/server2/cron.yaml +++ b/chrome/common/extensions/docs/server2/cron.yaml
@@ -2,4 +2,4 @@ - description: Repopulates all cached data. url: /_cron schedule: every 180 minutes - target: 3-48-2 + target: 3-49-0
diff --git a/chrome/common/extensions/docs/server2/jsc_view.py b/chrome/common/extensions/docs/server2/jsc_view.py index 967d0ef..2bf46d70 100644 --- a/chrome/common/extensions/docs/server2/jsc_view.py +++ b/chrome/common/extensions/docs/server2/jsc_view.py
@@ -233,7 +233,8 @@ 'functions': self._GenerateFunctions(type_.functions), 'events': self._GenerateEvents(type_.events), 'id': _CreateId(type_, 'type'), - 'availability': self._GetAvailabilityTemplate() + 'availability': self._GetAvailabilityTemplate( + is_enum=type_.property_type == model.PropertyType.ENUM) } self._RenderTypeInformation(type_, type_dict) return type_dict @@ -444,10 +445,16 @@ 'version': version } - def _GetAvailabilityTemplate(self): + def _GetAvailabilityTemplate(self, is_enum=False): '''Gets availability for the current node and returns an appropriate template object. ''' + # We don't show an availability warning for enums. + # TODO(devlin): We should also render enums differently, indicating that + # symbolic constants are available from version 44 onwards. + if is_enum: + return None + # Displaying deprecated status takes precedence over when the API # became stable. availability_info = self._current_node.GetDeprecated()
diff --git a/chrome/common/extensions/docs/templates/articles/settings_override.html b/chrome/common/extensions/docs/templates/articles/settings_override.html index e9b41a2..a71a7b7 100644 --- a/chrome/common/extensions/docs/templates/articles/settings_override.html +++ b/chrome/common/extensions/docs/templates/articles/settings_override.html
@@ -2,6 +2,7 @@ <p> Settings overrides are a way for extensions to override selected Chrome settings. +The API is available only on Windows. </p> <h2 id="others">Homepage, Search Provider, and Startup Pages</h2>
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc index 581855c..f212652a 100644 --- a/chrome/common/extensions/permissions/permission_set_unittest.cc +++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -1270,7 +1270,7 @@ extension->permissions_data()->HasAPIPermission(APIPermission::kSocket)); EXPECT_TRUE(VerifyOnePermissionMessage( extension->permissions_data(), - "Exchange data with any computer on the local network or internet")); + "Exchange data with any device on the local network or internet")); } TEST(PermissionsTest, GetWarningMessages_Socket_OneDomainTwoHostnames) { @@ -1288,8 +1288,8 @@ // order in the manifest file. EXPECT_TRUE(VerifyTwoPermissionMessages( extension->permissions_data(), - "Exchange data with any computer in the domain example.org", - "Exchange data with the computers named: " + "Exchange data with any device in the domain example.org", + "Exchange data with the devices named: " "b\xC3\xA5r.example.com foo.example.com", // "\xC3\xA5" = UTF-8 for lowercase A with ring above true)); @@ -1309,9 +1309,9 @@ // in alphabetical order regardless of the order in the manifest file. EXPECT_TRUE(VerifyTwoPermissionMessages( extension->permissions_data(), - "Exchange data with any computer in the domains: " + "Exchange data with any device in the domains: " "example.com foo.example.org", - "Exchange data with the computer named bar.example.org", true)); + "Exchange data with the device named bar.example.org", true)); } // Since platform apps always use isolated storage, they can't (silently)
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index bd6bd52..2393953 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -817,6 +817,11 @@ // which allows to bypass the user's proxy for captive portal authentication. const char kCaptivePortalAuthenticationIgnoresProxy[] = "proxy.captive_portal_ignores_proxy"; + +// This boolean controls whether the first window shown on first run should be +// unconditionally maximized, overriding the heuristic that normally chooses the +// window size. +const char kForceMaximizeOnFirstRun[] = "ui.force_maximize_on_first_run"; #endif // defined(OS_CHROMEOS) // The disabled messages in IPC logging.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index b44ea9f..ca290fa 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -270,6 +270,7 @@ extern const char kTouchVirtualKeyboardEnabled[]; extern const char kWakeOnWifiSsid[]; extern const char kCaptivePortalAuthenticationIgnoresProxy[]; +extern const char kForceMaximizeOnFirstRun[]; #endif // defined(OS_CHROMEOS) extern const char kIpcDisabledMessages[]; extern const char kShowHomeButton[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index f75359e..4f615f6 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h
@@ -45,25 +45,17 @@ #ifndef CHROME_COMMON_RENDER_MESSAGES_H_ #define CHROME_COMMON_RENDER_MESSAGES_H_ -// This enum is inside a struct so that we can forward-declare the struct in -// others headers without having to include this one. -struct ChromeViewHostMsg_GetPluginInfo_Status { - enum Value { - kAllowed, - kBlocked, - kBlockedByPolicy, - kDisabled, - kNotFound, - kNPAPINotSupported, - kOutdatedBlocked, - kOutdatedDisallowed, - kPlayImportantContent, - kUnauthorized, - }; - - ChromeViewHostMsg_GetPluginInfo_Status() : value(kAllowed) {} - - Value value; +enum class ChromeViewHostMsg_GetPluginInfo_Status { + kAllowed, + kBlocked, + kBlockedByPolicy, + kDisabled, + kNotFound, + kNPAPINotSupported, + kOutdatedBlocked, + kOutdatedDisallowed, + kPlayImportantContent, + kUnauthorized, }; namespace IPC { @@ -82,7 +74,7 @@ #define IPC_MESSAGE_START ChromeMsgStart -IPC_ENUM_TRAITS_MAX_VALUE(ChromeViewHostMsg_GetPluginInfo_Status::Value, +IPC_ENUM_TRAITS_MAX_VALUE(ChromeViewHostMsg_GetPluginInfo_Status, ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized) IPC_ENUM_TRAITS_MAX_VALUE(OmniboxFocusChangeReason, OMNIBOX_FOCUS_CHANGE_REASON_LAST) @@ -95,10 +87,6 @@ IPC_ENUM_TRAITS(blink::WebConsoleMessage::Level) IPC_ENUM_TRAITS(content::TopControlsState) -IPC_STRUCT_TRAITS_BEGIN(ChromeViewHostMsg_GetPluginInfo_Status) -IPC_STRUCT_TRAITS_MEMBER(value) -IPC_STRUCT_TRAITS_END() - // Output parameters for ChromeViewHostMsg_GetPluginInfo message. IPC_STRUCT_BEGIN(ChromeViewHostMsg_GetPluginInfo_Output) IPC_STRUCT_MEMBER(ChromeViewHostMsg_GetPluginInfo_Status, status)
diff --git a/chrome/installer/linux/common/apt.include b/chrome/installer/linux/common/apt.include index 25fd054..77d418c1 100644 --- a/chrome/installer/linux/common/apt.include +++ b/chrome/installer/linux/common/apt.include
@@ -87,7 +87,7 @@ ACTIVECONFIGS=$(grep -v "^[[:space:]]*\(#.*\)\?$" "$SOURCELIST" 2>/dev/null) # Check if the correct repository configuration is in there. - REPOMATCH=$(grep "^[[:space:]#]*\b$REPOCONFIG\b" "$SOURCELIST" \ + REPOMATCH=$(grep -E "^[[:space:]#]*\b($REPOCONFIG|$SSLREPOCONFIG)\b" "$SOURCELIST" \ 2>/dev/null) # Check if the correct repository is disabled. @@ -174,9 +174,9 @@ find_apt_sources SOURCELIST="$APT_SOURCESDIR/@@PACKAGE@@.list" if [ -r "$SOURCELIST" ]; then - REPOLINE=$(grep -E "^[[:space:]]*#[[:space:]]*$REPOCONFIG[[:space:]]*# disabled on upgrade to .*" "$SOURCELIST") + REPOLINE=$(grep -E "^[[:space:]]*#[[:space:]]*($REPOCONFIG|$SSLREPOCONFIG)[[:space:]]*# disabled on upgrade to .*" "$SOURCELIST") if [ $? -eq 0 ]; then - sed -i -e "s,^[[:space:]]*#[[:space:]]*\($REPOCONFIG\)[[:space:]]*# disabled on upgrade to .*,\1," \ + sed -i -e "s,^[[:space:]]*#[[:space:]]*\($REPOCONFIG\|$SSLREPOCONFIG\)[[:space:]]*# disabled on upgrade to .*,\1," \ "$SOURCELIST" LOGGER=$(which logger 2> /dev/null) if [ "$LOGGER" ]; then
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include index 1296ca8..14171f76 100644 --- a/chrome/installer/linux/common/installer.include +++ b/chrome/installer/linux/common/installer.include
@@ -73,6 +73,7 @@ -e "s#@@MAINTNAME@@#${MAINTNAME}#g" \ -e "s#@@MAINTMAIL@@#${MAINTMAIL}#g" \ -e "s#@@REPOCONFIG@@#${REPOCONFIG}#g" \ + -e "s#@@SSLREPOCONFIG@@#${SSLREPOCONFIG}#g" \ -e "s#@@SHORTDESC@@#${SHORTDESC}#g" \ -e "s#@@FULLDESC@@#${FULLDESC}#g" \ -e "s#@@DEFAULT_FLAGS@@#${DEFAULT_FLAGS:-}#g" \
diff --git a/chrome/installer/linux/common/variables.include b/chrome/installer/linux/common/variables.include index f3a17cd..79340cd 100644 --- a/chrome/installer/linux/common/variables.include +++ b/chrome/installer/linux/common/variables.include
@@ -3,3 +3,4 @@ # sources.list setting for @@PACKAGE@@ updates. REPOCONFIG="@@REPOCONFIG@@" +SSLREPOCONFIG="@@SSLREPOCONFIG@@"
diff --git a/chrome/installer/linux/debian/build.sh b/chrome/installer/linux/debian/build.sh index 533e986..c7f75a2 100755 --- a/chrome/installer/linux/debian/build.sh +++ b/chrome/installer/linux/debian/build.sh
@@ -233,6 +233,7 @@ "${BUILDDIR}/installer/theme/BRANDING") REPOCONFIG="deb http://dl.google.com/linux/chrome/deb/ stable main" +SSLREPOCONFIG="deb https://dl.google.com/linux/chrome/deb/ stable main" verify_channel # Some Debian packaging tools want these set.
diff --git a/chrome/installer/linux/rpm/build.sh b/chrome/installer/linux/rpm/build.sh index c3626a6..6110905 100755 --- a/chrome/installer/linux/rpm/build.sh +++ b/chrome/installer/linux/rpm/build.sh
@@ -281,6 +281,7 @@ "${BUILDDIR}/installer/theme/BRANDING") REPOCONFIG="http://dl.google.com/linux/${PACKAGE#google-}/rpm/stable" +SSLREPOCONFIG="https://dl.google.com/linux/${PACKAGE#google-}/rpm/stable" verify_channel export USR_BIN_SYMLINK_NAME="${PACKAGE}-${CHANNEL}"
diff --git a/chrome/installer/util/installation_validator.cc b/chrome/installer/util/installation_validator.cc index 0334ceb1..5c0e25f 100644 --- a/chrome/installer/util/installation_validator.cc +++ b/chrome/installer/util/installation_validator.cc
@@ -11,17 +11,13 @@ #include <string> #include "base/logging.h" -#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/version.h" -#include "base/win/registry.h" #include "chrome/common/chrome_switches.h" #include "chrome/installer/util/browser_distribution.h" #include "chrome/installer/util/google_update_constants.h" #include "chrome/installer/util/helper.h" -#include "chrome/installer/util/install_util.h" #include "chrome/installer/util/installation_state.h" -#include "chrome/installer/util/updating_app_registration_data.h" namespace installer { @@ -556,30 +552,6 @@ ProductBits::CHROME_SINGLE)); } -#if defined(GOOGLE_CHROME_BUILD) - if (!InstallUtil::IsChromeSxSProcess()) { - // Usage of the app launcher is tracked alongside Chrome. - const HKEY root_key = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - base::string16 launcher_key( - UpdatingAppRegistrationData(kAppLauncherGuid).GetVersionKey()); - base::win::RegKey key(root_key, launcher_key.c_str(), - KEY_QUERY_VALUE | KEY_WOW64_32KEY); - bool have_launcher = - key.Valid() && key.HasValue(google_update::kRegVersionField); - - BrowserDistribution* chrome_dist = - BrowserDistribution::GetSpecificDistribution( - BrowserDistribution::CHROME_BROWSER); - if (!have_launcher) { - LOG_IF(ERROR, product_state) << "App launcher is not installed with " - << chrome_dist->GetDisplayName(); - } else { - LOG_IF(ERROR, !product_state) << "App launcher is installed without " - << chrome_dist->GetDisplayName(); - } - } -#endif // GOOGLE_CHROME_BUILD - // Is Chrome Frame installed? product_state = machine_state.GetProductState(system_level,
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index e33064f..abb8170 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -656,7 +656,7 @@ frame->top()->document().url(), orig_mime_type, &output)); #else - output.status.value = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; + output.status = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; #endif *plugin = CreatePlugin(render_frame, frame, params, output); return true; @@ -693,12 +693,11 @@ blink::WebLocalFrame* frame, const WebPluginParams& original_params, const ChromeViewHostMsg_GetPluginInfo_Output& output) { - const ChromeViewHostMsg_GetPluginInfo_Status& status = output.status; const WebPluginInfo& info = output.plugin; const std::string& actual_mime_type = output.actual_mime_type; const base::string16& group_name = output.group_name; const std::string& identifier = output.group_identifier; - ChromeViewHostMsg_GetPluginInfo_Status::Value status_value = status.value; + ChromeViewHostMsg_GetPluginInfo_Status status = output.status; GURL url(original_params.url); std::string orig_mime_type = original_params.mimeType.utf8(); ChromePluginPlaceholder* placeholder = NULL; @@ -706,7 +705,7 @@ // If the browser plugin is to be enabled, this should be handled by the // renderer, so the code won't reach here due to the early exit in // OverrideCreatePlugin. - if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound || + if (status == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound || orig_mime_type == content::kBrowserPluginMimeType) { #if defined(OS_ANDROID) if (plugins::MobileYouTubePlugin::IsYouTubeURL(url, orig_mime_type)) { @@ -752,24 +751,22 @@ ? CONTENT_SETTINGS_TYPE_JAVASCRIPT : CONTENT_SETTINGS_TYPE_PLUGINS; - if ((status_value == - ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized || - status_value == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked) && + if ((status == ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized || + status == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked) && observer->IsPluginTemporarilyAllowed(identifier)) { - status_value = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; + status = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; } #if defined(OS_WIN) // In Windows we need to check if we can load NPAPI plugins. // For example, if the render view is in the Ash desktop, we should not. // If user is on ALLOW or DETECT setting, loading needs to be blocked here. - if ((status_value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed || - status_value == + if ((status == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed || + status == ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent) && info.type == content::WebPluginInfo::PLUGIN_TYPE_NPAPI) { if (observer->AreNPAPIPluginsBlocked()) - status_value = - ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; + status = ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; } #endif @@ -780,7 +777,7 @@ render_frame, frame, params, info, identifier, group_name, template_id, message, PlaceholderPosterInfo()); }; - switch (status_value) { + switch (status) { case ChromeViewHostMsg_GetPluginInfo_Status::kNotFound: { NOTREACHED(); break; @@ -838,11 +835,11 @@ error_message)); placeholder = create_blocked_plugin( IDR_BLOCKED_PLUGIN_HTML, - #if defined(OS_CHROMEOS) +#if defined(OS_CHROMEOS) l10n_util::GetStringUTF16(IDS_NACL_PLUGIN_BLOCKED)); - #else +#else l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); - #endif +#endif break; } } @@ -866,7 +863,7 @@ // https://crbug.com/471427 bool power_saver_enabled = !is_prerendering && - status_value == + status == ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent; if (info.name == ASCIIToUTF16(content::kFlashPluginName))
diff --git a/chrome/renderer/chrome_content_renderer_client_browsertest.cc b/chrome/renderer/chrome_content_renderer_client_browsertest.cc index fbaba81..14b2526 100644 --- a/chrome/renderer/chrome_content_renderer_client_browsertest.cc +++ b/chrome/renderer/chrome_content_renderer_client_browsertest.cc
@@ -133,7 +133,7 @@ params.mimeType = base::ASCIIToUTF16(mime_type); ChromeViewHostMsg_GetPluginInfo_Output output; - output.status.value = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; + output.status = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; ScopedMockPluginInfoFilter filter(render_thread_.get()); #if defined(ENABLE_PLUGINS) @@ -158,7 +158,7 @@ params.mimeType = base::ASCIIToUTF16(mime_type); ChromeViewHostMsg_GetPluginInfo_Output output; - output.status.value = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; + output.status = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; ScopedMockPluginInfoFilter filter(render_thread_.get()); #if defined(ENABLE_PLUGINS)
diff --git a/chrome/renderer/media/OWNERS b/chrome/renderer/media/OWNERS index cbadb65a..0b7e48d 100644 --- a/chrome/renderer/media/OWNERS +++ b/chrome/renderer/media/OWNERS
@@ -7,7 +7,7 @@ tommi@chromium.org xhwang@chromium.org +# For Cast streaming changes. per-file cast_*=hclam@chromium.org per-file cast_*=hubbe@chromium.org -per-file cast_*=mikhal@chromium.org -per-file cast_*=pwestin@google.com +per-file cast_*=miu@chromium.org
diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc index 7c40523..bbe675a 100644 --- a/chrome/renderer/media/cast_rtp_stream.cc +++ b/chrome/renderer/media/cast_rtp_stream.cc
@@ -151,9 +151,18 @@ std::vector<CastRtpParams> SupportedVideoParams() { std::vector<CastRtpParams> supported_params; + + // Prefer VP8 over H.264 for hardware encoder. + if (IsHardwareVP8EncodingSupported()) + supported_params.push_back(CastRtpParams(DefaultVp8Payload())); if (IsHardwareH264EncodingSupported()) supported_params.push_back(CastRtpParams(DefaultH264Payload())); - supported_params.push_back(CastRtpParams(DefaultVp8Payload())); + + // Propose the default software VP8 encoder, if no hardware encoders are + // available. + if (supported_params.empty()) + supported_params.push_back(CastRtpParams(DefaultVp8Payload())); + return supported_params; }
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc index 862627c..61a84ba 100644 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc +++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -64,7 +64,7 @@ params, html_data, GURL(kPluginPlaceholderDataURL)), - status_(new ChromeViewHostMsg_GetPluginInfo_Status), + status_(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed), title_(title), #if defined(ENABLE_PLUGIN_INSTALLATION) placeholder_routing_id_(MSG_ROUTING_NONE), @@ -186,8 +186,8 @@ } void ChromePluginPlaceholder::SetStatus( - const ChromeViewHostMsg_GetPluginInfo_Status& status) { - status_->value = status.value; + ChromeViewHostMsg_GetPluginInfo_Status status) { + status_ = status; } #if defined(ENABLE_PLUGIN_INSTALLATION) @@ -242,7 +242,7 @@ void ChromePluginPlaceholder::OnFoundMissingPlugin( const base::string16& plugin_name) { - if (status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) + if (status_ == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound) SetMessage(l10n_util::GetStringFUTF16(IDS_PLUGIN_FOUND, plugin_name)); has_host_ = true; plugin_name_ = plugin_name; @@ -254,7 +254,7 @@ void ChromePluginPlaceholder::OnFinishedDownloadingPlugin() { bool is_installing = - status_->value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; + status_ == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; SetMessage(l10n_util::GetStringFUTF16( is_installing ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING, plugin_name_)); @@ -287,7 +287,7 @@ document.url(), mime_type, &output)); - if (output.status.value == status_->value) + if (output.status == status_) return; WebPlugin* new_plugin = ChromeContentRendererClient::CreatePlugin( render_frame(), GetFrame(), GetPluginParams(), output);
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h index d7ecf76..c308732dc 100644 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.h +++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -13,7 +13,7 @@ class Size; } -struct ChromeViewHostMsg_GetPluginInfo_Status; +enum class ChromeViewHostMsg_GetPluginInfo_Status; // This contains information specifying the poster image of plugin placeholders. // The default constructor specifies no poster image. @@ -55,7 +55,7 @@ content::RenderFrame* render_frame, const base::FilePath& plugin_path); - void SetStatus(const ChromeViewHostMsg_GetPluginInfo_Status& status); + void SetStatus(ChromeViewHostMsg_GetPluginInfo_Status status); #if defined(ENABLE_PLUGIN_INSTALLATION) int32 CreateRoutingId(); @@ -101,9 +101,7 @@ void OnCancelledDownloadingPlugin(); #endif - // We use a scoped_ptr so we can forward-declare the struct; it's defined in - // an IPC message file which can't be easily included in other header files. - scoped_ptr<ChromeViewHostMsg_GetPluginInfo_Status> status_; + ChromeViewHostMsg_GetPluginInfo_Status status_; base::string16 title_;
diff --git a/chrome/renderer/plugins/shadow_dom_plugin_placeholder.cc b/chrome/renderer/plugins/shadow_dom_plugin_placeholder.cc index 8441f76..9175a10 100644 --- a/chrome/renderer/plugins/shadow_dom_plugin_placeholder.cc +++ b/chrome/renderer/plugins/shadow_dom_plugin_placeholder.cc
@@ -53,10 +53,10 @@ orig_mime_type, &output)); #else - output.status.value = Status::kNotFound; + output.status = Status::kNotFound; #endif - if (output.status.value == Status::kNotFound) { + if (output.status == Status::kNotFound) { // TODO(jbroman): Handle YouTube specially here, as in // ChromeContentRendererClient::CreatePlugin. PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type,
diff --git a/chrome/test/android/unit_tests_apk/src/org/chromium/chrome/unit_tests_apk/ChromeNativeTestApplication.java b/chrome/test/android/unit_tests_apk/src/org/chromium/chrome/unit_tests_apk/ChromeNativeTestApplication.java index 910e81c..835d468b 100644 --- a/chrome/test/android/unit_tests_apk/src/org/chromium/chrome/unit_tests_apk/ChromeNativeTestApplication.java +++ b/chrome/test/android/unit_tests_apk/src/org/chromium/chrome/unit_tests_apk/ChromeNativeTestApplication.java
@@ -5,7 +5,7 @@ package org.chromium.chrome.unit_tests_apk; import org.chromium.chrome.browser.ChromiumApplication; -import org.chromium.chrome.browser.PKCS11AuthenticationManager; +import org.chromium.chrome.browser.smartcard.PKCS11AuthenticationManager; /** * A stub implementation of the chrome application to be used in chrome unit_tests.
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc index ce2cf19..46ec927e 100644 --- a/chrome/test/base/testing_profile_manager.cc +++ b/chrome/test/base/testing_profile_manager.cc
@@ -240,5 +240,7 @@ profile_manager_ = new testing::ProfileManager(profiles_dir_.path()); browser_process_->SetProfileManager(profile_manager_); // Takes ownership. + profile_manager_->GetProfileInfoCache(). + set_disable_avatar_download_for_testing(true); called_set_up_ = true; }
diff --git a/chrome/test/data/extensions/api_test/file_browser/mount_test/test.js b/chrome/test/data/extensions/api_test/file_browser/mount_test/test.js index ff09363..459a280 100644 --- a/chrome/test/data/extensions/api_test/file_browser/mount_test/test.js +++ b/chrome/test/data/extensions/api_test/file_browser/mount_test/test.js
@@ -7,6 +7,7 @@ volumeId: 'removable:mount_path1', volumeLabel: 'mount_path1', sourcePath: 'device_path1', + volumeSource: 'device', volumeType: 'removable', deviceType: 'usb', devicePath: 'system_path_prefix1', @@ -20,6 +21,7 @@ volumeId: 'removable:mount_path2', volumeLabel: 'mount_path2', sourcePath: 'device_path2', + volumeSource: 'device', volumeType: 'removable', deviceType: 'mobile', devicePath: 'system_path_prefix2', @@ -33,6 +35,7 @@ volumeId: 'removable:mount_path3', volumeLabel: 'mount_path3', sourcePath: 'device_path3', + volumeSource: 'device', volumeType: 'removable', deviceType: 'optical', devicePath: 'system_path_prefix3', @@ -45,6 +48,7 @@ var expectedDownloadsVolume = { volumeId: /^downloads:Downloads[^\/]*$/, volumeLabel: '', + volumeSource: 'device', volumeType: 'downloads', isReadOnly: false, hasMedia: false, @@ -55,6 +59,7 @@ volumeId: /^drive:drive[^\/]*$/, volumeLabel: '', sourcePath: /^\/special\/drive[^\/]*$/, + volumeSource: 'network', volumeType: 'drive', isReadOnly: false, hasMedia: false, @@ -65,6 +70,7 @@ volumeId: 'archive:archive_mount_path', volumeLabel: 'archive_mount_path', sourcePath: /removable\/mount_path3\/archive.zip$/, + volumeSource: 'file', volumeType: 'archive', isReadOnly: true, hasMedia: false,
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/get_all/test.js b/chrome/test/data/extensions/api_test/file_system_provider/get_all/test.js index a0fa062e..993925f 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/get_all/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/get_all/test.js
@@ -86,6 +86,8 @@ fileSystems[0].displayName); chrome.test.assertTrue( fileSystems[0].writable); + chrome.test.assertEq( + 'NETWORK', fileSystems[0].source); chrome.test.assertEq(2, fileSystems[0].openedFilesLimit); })); @@ -100,6 +102,8 @@ test_util.FILE_SYSTEM_NAME, fileSystem.displayName); chrome.test.assertTrue(fileSystem.writable); + chrome.test.assertEq( + 'NETWORK', fileSystem.source); chrome.test.assertEq(2, fileSystem.openedFilesLimit); })); @@ -113,7 +117,7 @@ function(error) { chrome.test.fail(error.name); }); - }), {writable: true, openedFilesLimit: 2}); + }), {writable: true, openedFilesLimit: 2, source: 'NETWORK'}); }, // Verifies that after unmounting, the file system is not available in
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/mount/test.js b/chrome/test/data/extensions/api_test/file_system_provider/mount/test.js index 83e2c37..022d384 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/mount/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/mount/test.js
@@ -65,7 +65,11 @@ function successfulMount() { var fileSystemId = 'caramel-candy'; chrome.fileSystemProvider.mount( - {fileSystemId: fileSystemId, displayName: 'caramel-candy.zip'}, + { + fileSystemId: fileSystemId, + displayName: 'caramel-candy.zip', + source: 'FILE' + }, chrome.test.callbackPass(function() { chrome.fileManagerPrivate.getVolumeMetadataList(function(volumeList) { var volumeInfo;
diff --git a/chrome/test/data/extensions/api_test/mdns/api/get_max_service_instances.html b/chrome/test/data/extensions/api_test/mdns/api/get_max_service_instances.html new file mode 100644 index 0000000..f8b22d1e --- /dev/null +++ b/chrome/test/data/extensions/api_test/mdns/api/get_max_service_instances.html
@@ -0,0 +1 @@ +<script src="get_max_service_instances.js"></script>
diff --git a/chrome/test/data/extensions/api_test/mdns/api/get_max_service_instances.js b/chrome/test/data/extensions/api_test/mdns/api/get_max_service_instances.js new file mode 100644 index 0000000..03cd0c83 --- /dev/null +++ b/chrome/test/data/extensions/api_test/mdns/api/get_max_service_instances.js
@@ -0,0 +1,13 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +onload = function() { + chrome.test.runTests([ + function getMaxServiceInstancesPerEvent() { + // Ensure that the constant is actually set. + chrome.test.assertTrue(chrome.mdns.MAX_SERVICE_INSTANCES_PER_EVENT > 0); + chrome.test.notifyPass(); + } + ]); +};
diff --git a/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js b/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js index fb46498..fae9c574 100644 --- a/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js +++ b/chrome/test/data/extensions/api_test/messaging/externally_connectable/sites/assertions.js
@@ -29,11 +29,15 @@ // SafeBuiltins does not support getters yet. See crbug.com/463526. // Clobbering Function.call would make it impossible to implement these tests. // Clobbering Object.valueOf breaks v8. + // Clobbering %FunctionPrototype%.caller and .arguments will break because + // these properties are poisoned accessors in ES6. if (name == 'constructor' || name == 'toString' || name == '__proto__' || name == 'name' && typeof obj == 'function' || qualifiedName == 'Function.call' || + (obj !== Function && qualifiedName == 'Function.caller') || + (obj !== Function && qualifiedName == 'Function.arguments') || qualifiedName == 'Object.valueOf') { return; }
diff --git a/chrome/test/data/extensions/api_test/tab_capture/performance.js b/chrome/test/data/extensions/api_test/tab_capture/performance.js index 7f315e213..bfb0c15 100644 --- a/chrome/test/data/extensions/api_test/tab_capture/performance.js +++ b/chrome/test/data/extensions/api_test/tab_capture/performance.js
@@ -10,6 +10,7 @@ // Global to prevent gc from eating the video tag. var video = null; +var capture_stream = null; function TestStream(stream) { // Create video and canvas elements, but no need to append them to the @@ -38,6 +39,9 @@ // Note that the API testing framework might not terminate if we keep // animating and capturing, so we have to make sure that we stop doing // that here. + if (capture_stream) { + capture_stream.stop(); + } stream.stop(); return; } @@ -64,6 +68,7 @@ // Set up a WebRTC connection and pipe |stream| through it. function testThroughWebRTC(stream) { + capture_stream = stream; console.log("Testing through webrtc."); var sender = new webkitRTCPeerConnection(null); var receiver = new webkitRTCPeerConnection(null);
diff --git a/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js b/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js index 8d4539c..93be223 100644 --- a/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js +++ b/chrome/test/data/extensions/platform_apps/music_manager_private/device_id_value_returned/chrometest.js
@@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var deviceIdMaybeUndefined; - function runTests() { chrome.test.runTests([ function test() { chrome.musicManagerPrivate.getDeviceId(function(id) { console.log('Device ID=' + id); - if (!id) { - chrome.test.assertEq(true, deviceIdMaybeUndefined) - } else { + if (id) { + // This block is not entered in VMs (e.g. the bots) which return + // dummy MACs. chrome.test.assertEq('string', typeof id); chrome.test.assertTrue(id.length >= 8); } @@ -24,8 +22,6 @@ window.onload = function() { chrome.test.getConfig(function(config) { console.log('customArg=' + config.customArg); - deviceIdMaybeUndefined = - (config.customArg === 'device_id_may_be_undefined'); runTests(); }); }
diff --git a/chrome/test/data/extensions/platform_apps/web_view/simple/main.js b/chrome/test/data/extensions/platform_apps/web_view/simple/main.js index 7e064839..dee6c63 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/simple/main.js +++ b/chrome/test/data/extensions/platform_apps/web_view/simple/main.js
@@ -4,6 +4,8 @@ function CreateWebViewAndGuest(callback) { var webview = document.createElement('webview'); + webview.allowtransparency = true; + webview.allowscaling = true; var onLoadStop = function(e) { chrome.test.sendMessage('WebViewTest.LAUNCHED'); webview.removeEventListener('loadstop', onLoadStop);
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 38a73198..01aac319 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -2213,6 +2213,14 @@ "os": ["chromeos"], "can_be_recommended": true }, + + "ForceMaximizeOnFirstRun": { + "os": ["chromeos"], + "test_policy": { "ForceMaximizeOnFirstRun": true }, + "pref_mappings": [ + { "pref": "ui.force_maximize_on_first_run" } + ] + }, "----- Chrome OS device policies ---------------------------------------": {},
diff --git a/chrome/test/mini_installer/config/chrome_system_installed.prop b/chrome/test/mini_installer/config/chrome_system_installed.prop index 2a336d9..1e67d3c2 100644 --- a/chrome/test/mini_installer/config/chrome_system_installed.prop +++ b/chrome/test/mini_installer/config/chrome_system_installed.prop
@@ -25,6 +25,13 @@ "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} } }, + "HKEY_LOCAL_MACHINE\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "required", + "values": { + "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} + } + }, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": { "exists": "required", "values": {
diff --git a/chrome/test/mini_installer/config/chrome_system_not_installed.prop b/chrome/test/mini_installer/config/chrome_system_not_installed.prop index e10910b..03d04b95 100644 --- a/chrome/test/mini_installer/config/chrome_system_not_installed.prop +++ b/chrome/test/mini_installer/config/chrome_system_not_installed.prop
@@ -7,6 +7,10 @@ "exists": "forbidden"}, "HKEY_LOCAL_MACHINE\\$BINARIES_UPDATE_REGISTRY_SUBKEY": { "exists": "forbidden"}, + "HKEY_LOCAL_MACHINE\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "forbidden" + }, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": {"exists": "forbidden"}, "HKEY_LOCAL_MACHINE\\Software\\Classes\\$CHROME_SHORT_NAME": {
diff --git a/chrome/test/mini_installer/config/chrome_user_installed.prop b/chrome/test/mini_installer/config/chrome_user_installed.prop index ed9f19e..1e12544 100644 --- a/chrome/test/mini_installer/config/chrome_user_installed.prop +++ b/chrome/test/mini_installer/config/chrome_user_installed.prop
@@ -25,6 +25,13 @@ "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} } }, + "HKEY_CURRENT_USER\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "required", + "values": { + "pv": {"type": "SZ", "data": "$MINI_INSTALLER_FILE_VERSION"} + } + }, "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": { "exists": "required", "values": {
diff --git a/chrome/test/mini_installer/config/chrome_user_not_installed.prop b/chrome/test/mini_installer/config/chrome_user_not_installed.prop index 7898f647..20abd40 100644 --- a/chrome/test/mini_installer/config/chrome_user_not_installed.prop +++ b/chrome/test/mini_installer/config/chrome_user_not_installed.prop
@@ -7,6 +7,10 @@ {"exists": "forbidden"}, "HKEY_CURRENT_USER\\$BINARIES_UPDATE_REGISTRY_SUBKEY": {"exists": "forbidden"}, + "HKEY_CURRENT_USER\\$LAUNCHER_UPDATE_REGISTRY_SUBKEY": { + "condition": "'$CHROME_SHORT_NAME' == 'Chrome'", + "exists": "forbidden" + }, "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\$CHROME_LONG_NAME": {"exists": "forbidden"}, "HKEY_CURRENT_USER\\Software\\Classes\\$CHROME_SHORT_NAME$USER_SPECIFIC_REGISTRY_SUFFIX": {
diff --git a/chrome/test/mini_installer/variable_expander.py b/chrome/test/mini_installer/variable_expander.py index 4bd7892d..318367b2 100644 --- a/chrome/test/mini_installer/variable_expander.py +++ b/chrome/test/mini_installer/variable_expander.py
@@ -72,6 +72,8 @@ key, of Chrome for Google Update. * $CHROME_UPDATE_REGISTRY_SUBKEY_SXS: the registry key, excluding the root key, of Chrome SxS for Google Update. + * $LAUNCHER_UPDATE_REGISTRY_SUBKEY: the registry key, excluding the root + key, of the app launcher for Google Update if $SUPPORTS_SXS. * $LOCAL_APPDATA: the unquoted path to the Local Application Data folder. * $MINI_INSTALLER: the unquoted path to the mini_installer. @@ -127,7 +129,10 @@ 'CHROME_SHORT_NAME_SXS': 'ChromeCanary', 'CHROME_UPDATE_REGISTRY_SUBKEY_SXS': ( 'Software\\Google\\Update\\Clients\\' - '{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}') + '{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}'), + 'LAUNCHER_UPDATE_REGISTRY_SUBKEY': ( + 'Software\\Google\\Update\\Clients\\' + '{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}') }) elif mini_installer_product_name == 'Chromium Installer': self._variable_mapping.update({
diff --git a/chrome/test/mini_installer/verifier.py b/chrome/test/mini_installer/verifier.py index f3e930e..053096b 100644 --- a/chrome/test/mini_installer/verifier.py +++ b/chrome/test/mini_installer/verifier.py
@@ -49,4 +49,4 @@ Returns: The result of the evaluated condition. """ - return eval(condition, {'__builtins__': None}, None) + return eval(condition, {'__builtins__': {'False': False, 'True': True}})
diff --git a/chromecast/browser/android/external_video_surface_container_impl.cc b/chromecast/browser/android/external_video_surface_container_impl.cc index e1f7e8b..e830575 100644 --- a/chromecast/browser/android/external_video_surface_container_impl.cc +++ b/chromecast/browser/android/external_video_surface_container_impl.cc
@@ -11,17 +11,24 @@ namespace chromecast { namespace shell { - -ExternalVideoSurfaceContainerImpl::ExternalVideoSurfaceContainerImpl( +// static +ExternalVideoSurfaceContainerImpl* ExternalVideoSurfaceContainerImpl::Create( content::WebContents* web_contents) { content::ContentViewCore* cvc = content::ContentViewCore::FromWebContents(web_contents); - if (cvc) { - JNIEnv* env = base::android::AttachCurrentThread(); - jobject_.Reset( - Java_ExternalVideoSurfaceContainer_create( - env, reinterpret_cast<intptr_t>(this), cvc->GetJavaObject().obj())); - } + if (!cvc) + return nullptr; + base::android::ScopedJavaLocalRef<jobject> jcvc = cvc->GetJavaObject(); + if (jcvc.is_null()) + return nullptr; + return new ExternalVideoSurfaceContainerImpl(jcvc); +} + +ExternalVideoSurfaceContainerImpl::ExternalVideoSurfaceContainerImpl( + base::android::ScopedJavaLocalRef<jobject> java_content_view_core) { + JNIEnv* env = base::android::AttachCurrentThread(); + jobject_.Reset(Java_ExternalVideoSurfaceContainer_create( + env, reinterpret_cast<intptr_t>(this), java_content_view_core.obj())); } ExternalVideoSurfaceContainerImpl::~ExternalVideoSurfaceContainerImpl() {
diff --git a/chromecast/browser/android/external_video_surface_container_impl.h b/chromecast/browser/android/external_video_surface_container_impl.h index 434071db..d864d06 100644 --- a/chromecast/browser/android/external_video_surface_container_impl.h +++ b/chromecast/browser/android/external_video_surface_container_impl.h
@@ -21,7 +21,8 @@ typedef base::Callback<void(int, jobject)> SurfaceCreatedCB; typedef base::Callback<void(int)> SurfaceDestroyedCB; - ExternalVideoSurfaceContainerImpl(content::WebContents* contents); + static ExternalVideoSurfaceContainerImpl* Create( + content::WebContents* web_contents); // ExternalVideoSurfaceContainer implementation. void RequestExternalVideoSurface( @@ -40,6 +41,8 @@ void SurfaceDestroyed(JNIEnv* env, jobject obj, jint player_id); private: + explicit ExternalVideoSurfaceContainerImpl( + base::android::ScopedJavaLocalRef<jobject> java_content_view_core); ~ExternalVideoSurfaceContainerImpl() override; base::android::ScopedJavaGlobalRef<jobject> jobject_;
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 2fc59c2d..9fe57ce 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -327,7 +327,7 @@ content::ExternalVideoSurfaceContainer* CastContentBrowserClient::OverrideCreateExternalVideoSurfaceContainer( content::WebContents* web_contents) { - return new ExternalVideoSurfaceContainerImpl(web_contents); + return ExternalVideoSurfaceContainerImpl::Create(web_contents); } #endif // defined(OS_ANDROID) && defined(VIDEO_HOLE)
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc index 57091c7..5ac347ba 100644 --- a/chromecast/browser/url_request_context_factory.cc +++ b/chromecast/browser/url_request_context_factory.cc
@@ -16,13 +16,13 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "net/cert/cert_verifier.h" +#include "net/cert_net/nss_ocsp.h" #include "net/cookies/cookie_store.h" #include "net/dns/host_resolver.h" #include "net/http/http_auth_handler_factory.h" #include "net/http/http_network_layer.h" #include "net/http/http_server_properties_impl.h" #include "net/http/http_stream_factory.h" -#include "net/ocsp/nss_ocsp.h" #include "net/proxy/proxy_service.h" #include "net/socket/next_proto.h" #include "net/ssl/channel_id_service.h"
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp index fc4dbd5..b349d891 100644 --- a/chromecast/chromecast.gyp +++ b/chromecast/chromecast.gyp
@@ -354,14 +354,11 @@ 'type': 'none', 'dependencies': [ '../third_party/icu/icu.gyp:icudata', - '../v8/tools/gyp/v8.gyp:v8_external_snapshot', ], 'copies': [{ 'destination': '<(PRODUCT_DIR)/assets', 'files': [ '<(PRODUCT_DIR)/icudtl.dat', - '<(PRODUCT_DIR)/natives_blob.bin', - '<(PRODUCT_DIR)/snapshot_blob.bin', ], }], },
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 05c7032..cda6da34 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -6953.0.0 \ No newline at end of file +6956.0.0 \ No newline at end of file
diff --git a/chromeos/login/auth/login_performer.cc b/chromeos/login/auth/login_performer.cc index 5600e377..a773ad6 100644 --- a/chromeos/login/auth/login_performer.cc +++ b/chromeos/login/auth/login_performer.cc
@@ -143,6 +143,7 @@ AuthorizationMode auth_mode) { std::string email = gaia::CanonicalizeEmail(user_context.GetUserID()); bool wildcard_match = false; + if (!IsUserWhitelisted(email, &wildcard_match)) { NotifyWhitelistCheckFailure(); return;
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 6916cb7..70dd8ade 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -135,7 +135,7 @@ <!-- Autofill infobar --> <message name="IDS_AUTOFILL_CC_INFOBAR_ACCEPT" desc="Text to show for the Autofill credit card request infobar accept button."> - Save info + Save </message> <message name="IDS_AUTOFILL_CC_INFOBAR_DENY" desc="Text to show for the Autofill credit card request infobar deny button."> Don't save
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 99e0772f..1dab80f0 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -175,6 +175,9 @@ 'copresence/rpc/rpc_handler_unittest.cc', 'copresence/timed_map_unittest.cc', ], + 'cronet_unittest_sources': [ + 'cronet/histogram_manager_unittest.cc', + ], 'enhanced_bookmarks_unittest_sources': [ 'enhanced_bookmarks/enhanced_bookmark_model_unittest.cc', 'enhanced_bookmarks/image_store_ios_unittest.mm', @@ -255,7 +258,6 @@ 'metrics/daily_event_unittest.cc', 'metrics/gpu/gpu_metrics_provider_unittest.cc', 'metrics/histogram_encoder_unittest.cc', - 'metrics/histogram_manager_unittest.cc', 'metrics/machine_id_provider_win_unittest.cc', 'metrics/metrics_hashes_unittest.cc', 'metrics/metrics_log_manager_unittest.cc', @@ -389,14 +391,14 @@ 'precache/core/precache_url_table_unittest.cc', ], 'proximity_auth_unittest_sources': [ - 'proximity_auth/base64url_unittest.cc', 'proximity_auth/bluetooth_connection_finder_unittest.cc', 'proximity_auth/bluetooth_connection_unittest.cc', 'proximity_auth/client_unittest.cc', 'proximity_auth/connection_unittest.cc', - 'proximity_auth/cryptauth/cryptauth_account_token_fetcher_unittest.cc', + 'proximity_auth/cryptauth/base64url_unittest.cc', + 'proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl_unittest.cc', 'proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc', - 'proximity_auth/cryptauth/cryptauth_client_unittest.cc', + 'proximity_auth/cryptauth/cryptauth_client_impl_unittest.cc', 'proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc', 'proximity_auth/proximity_auth_system_unittest.cc', 'proximity_auth/remote_status_update_unittest.cc', @@ -880,6 +882,7 @@ }], ['OS == "android"', { 'sources': [ + '<@(cronet_unittest_sources)', 'data_reduction_proxy/content/browser/data_reduction_proxy_debug_blocking_page_unittest.cc', 'data_reduction_proxy/content/browser/data_reduction_proxy_debug_resource_throttle_unittest.cc', 'data_reduction_proxy/content/browser/data_reduction_proxy_debug_ui_manager_unittest.cc', @@ -901,6 +904,7 @@ 'web_modal/web_contents_modal_dialog_manager_unittest.cc', ], 'dependencies': [ + 'components.gyp:cronet_static', 'components.gyp:data_reduction_proxy_content', '../testing/android/native_test.gyp:native_test_native_code', ],
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc index c44abfb..07adc4d8 100644 --- a/components/content_settings/core/browser/content_settings_default_provider.cc +++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -39,34 +39,34 @@ // default content setting. This array must be kept in sync with the enum // |ContentSettingsType|. const DefaultContentSettingInfo kDefaultSettings[] = { - {prefs::kDefaultCookiesSetting, CONTENT_SETTING_ALLOW, true}, - {prefs::kDefaultImagesSetting, CONTENT_SETTING_ALLOW, true}, - {prefs::kDefaultJavaScriptSetting, CONTENT_SETTING_ALLOW, true}, - {prefs::kDefaultPluginsSetting, CONTENT_SETTING_ALLOW, true}, - {prefs::kDefaultPopupsSetting, CONTENT_SETTING_BLOCK, true}, - {prefs::kDefaultGeolocationSetting, CONTENT_SETTING_ASK, false}, - {prefs::kDefaultNotificationsSetting, CONTENT_SETTING_ASK, false}, - {prefs::kDefaultAutoSelectCertificateSetting, CONTENT_SETTING_DEFAULT, - false}, - {prefs::kDefaultFullScreenSetting, CONTENT_SETTING_ASK, true}, - {prefs::kDefaultMouseLockSetting, CONTENT_SETTING_ASK, true}, - {prefs::kDefaultMixedScriptSetting, CONTENT_SETTING_DEFAULT, true}, - {prefs::kDefaultMediaStreamSetting, CONTENT_SETTING_ASK, false}, - {prefs::kDefaultMediaStreamMicSetting, CONTENT_SETTING_ASK, false}, - {prefs::kDefaultMediaStreamCameraSetting, CONTENT_SETTING_ASK, false}, - {prefs::kDefaultProtocolHandlersSetting, CONTENT_SETTING_DEFAULT, true}, - {prefs::kDefaultPpapiBrokerSetting, CONTENT_SETTING_ASK, false}, - {prefs::kDefaultAutomaticDownloadsSetting, CONTENT_SETTING_ASK, true}, - {prefs::kDefaultMidiSysexSetting, CONTENT_SETTING_ASK, true}, - {prefs::kDefaultPushMessagingSetting, CONTENT_SETTING_ASK, true}, - {prefs::kDefaultSSLCertDecisionsSetting, CONTENT_SETTING_ALLOW, false}, + + {prefs::kDefaultCookiesSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultImagesSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultJavaScriptSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultPluginsSetting, CONTENT_SETTING_ALLOW, true}, + {prefs::kDefaultPopupsSetting, CONTENT_SETTING_BLOCK, true}, + {prefs::kDefaultGeolocationSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultNotificationsSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultAutoSelectCertificateSetting, CONTENT_SETTING_DEFAULT, false}, + {prefs::kDefaultFullScreenSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMouseLockSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMixedScriptSetting, CONTENT_SETTING_DEFAULT, true}, + {prefs::kDefaultMediaStreamSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultMediaStreamMicSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultMediaStreamCameraSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultProtocolHandlersSetting, CONTENT_SETTING_DEFAULT, true}, + {prefs::kDefaultPpapiBrokerSetting, CONTENT_SETTING_ASK, false}, + {prefs::kDefaultAutomaticDownloadsSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMidiSysexSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultPushMessagingSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultSSLCertDecisionsSetting, CONTENT_SETTING_ALLOW, false}, #if defined(OS_WIN) - {prefs::kDefaultMetroSwitchToDesktopSetting, CONTENT_SETTING_ASK, true}, + {prefs::kDefaultMetroSwitchToDesktopSetting, CONTENT_SETTING_ASK, true}, #elif defined(OS_ANDROID) || defined(OS_CHROMEOS) - {prefs::kDefaultProtectedMediaIdentifierSetting, CONTENT_SETTING_ASK, - false}, + {prefs::kDefaultProtectedMediaIdentifierSetting, CONTENT_SETTING_ASK, false}, #endif - {prefs::kDefaultAppBannerSetting, CONTENT_SETTING_DEFAULT, false} + {prefs::kDefaultAppBannerSetting, CONTENT_SETTING_DEFAULT, false} + }; static_assert(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES, "kDefaultSettings should have CONTENT_SETTINGS_NUM_TYPES " @@ -118,7 +118,7 @@ // Register individual default setting preferences. // TODO(msramek): The aggregate preference above is deprecated. Remove it // after two stable releases. - for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { registry->RegisterIntegerPref( kDefaultSettings[i].pref_name, kDefaultSettings[i].default_value, @@ -220,7 +220,7 @@ &DefaultProvider::OnPreferenceChanged, base::Unretained(this)); pref_change_registrar_.Add(prefs::kDefaultContentSettings, callback); - for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) pref_change_registrar_.Add(kDefaultSettings[i].pref_name, callback); } @@ -305,7 +305,7 @@ void DefaultProvider::ReadDefaultSettings() { base::AutoLock lock(lock_); - for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { ContentSettingsType content_type = ContentSettingsType(i); ChangeSetting(content_type, ReadIndividualPref(content_type).get()); } @@ -313,7 +313,7 @@ bool DefaultProvider::IsValueEmptyOrDefault(ContentSettingsType content_type, base::Value* value) { - return (value == NULL || + return (!value || ValueToContentSetting(value) == kDefaultSettings[content_type].default_value); } @@ -321,11 +321,8 @@ void DefaultProvider::ChangeSetting(ContentSettingsType content_type, base::Value* value) { if (!value) { - default_settings_[content_type].reset( - kDefaultSettings[content_type].default_value != CONTENT_SETTING_DEFAULT - ? new base::FundamentalValue( - kDefaultSettings[content_type].default_value) - : NULL); + default_settings_[content_type].reset(ContentSettingToValue( + kDefaultSettings[content_type].default_value).release()); } else { default_settings_[content_type].reset(value->DeepCopy()); } @@ -385,21 +382,20 @@ scoped_ptr<ValueMap> dictionary = ReadDictionaryPref(); - for (ValueMap::iterator it = dictionary->begin(); - it != dictionary->end(); ++it) { - if (!kDefaultSettings[it->first].syncable) + for (const auto& it : *dictionary) { + if (!kDefaultSettings[it.first].syncable) continue; - DCHECK(default_settings_.find(it->first) != default_settings_.end()); - ChangeSetting(it->first, it->second.get()); - WriteIndividualPref(it->first, it->second.get()); - to_notify.push_back(it->first); + DCHECK(default_settings_.find(it.first) != default_settings_.end()); + ChangeSetting(it.first, it.second.get()); + WriteIndividualPref(it.first, it.second.get()); + to_notify.push_back(it.first); } } else { // Find out which content setting the preference corresponds to. ContentSettingsType content_type = CONTENT_SETTINGS_TYPE_DEFAULT; - for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { if (kDefaultSettings[i].pref_name == name) { content_type = ContentSettingsType(i); break; @@ -423,10 +419,10 @@ to_notify.push_back(content_type); } - for (size_t i = 0; i < to_notify.size(); ++i) { + for (const ContentSettingsType content_type : to_notify) { NotifyObservers(ContentSettingsPattern(), ContentSettingsPattern(), - to_notify[i], + content_type, std::string()); } } @@ -434,11 +430,7 @@ scoped_ptr<base::Value> DefaultProvider::ReadIndividualPref( ContentSettingsType content_type) { int int_value = prefs_->GetInteger(kDefaultSettings[content_type].pref_name); - - if (int_value == CONTENT_SETTING_DEFAULT) - return make_scoped_ptr((base::Value*)NULL); - else - return make_scoped_ptr(new base::FundamentalValue(int_value)); + return ContentSettingToValue(IntToContentSetting(int_value)).Pass(); } scoped_ptr<DefaultProvider::ValueMap> DefaultProvider::ReadDictionaryPref() { @@ -472,10 +464,9 @@ void DefaultProvider::ForceDefaultsToBeExplicit(ValueMap* value_map) { for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { ContentSettingsType type = ContentSettingsType(i); - if (!(*value_map)[type].get() && - kDefaultSettings[i].default_value != CONTENT_SETTING_DEFAULT) { - (*value_map)[type].reset( - new base::FundamentalValue(kDefaultSettings[i].default_value)); + if (!(*value_map)[type].get()) { + (*value_map)[type].reset(ContentSettingToValue( + kDefaultSettings[i].default_value).release()); } } } @@ -483,26 +474,26 @@ scoped_ptr<DefaultProvider::ValueMap> DefaultProvider::GetSettingsFromDictionary( const base::DictionaryValue* dictionary) { + scoped_ptr<ValueMap> value_map(new ValueMap()); if (!dictionary) - return make_scoped_ptr(new ValueMap()); - ValueMap* value_map = new ValueMap(); + return value_map.Pass(); for (base::DictionaryValue::Iterator i(*dictionary); !i.IsAtEnd(); i.Advance()) { const std::string& content_type(i.key()); - for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { + for (int type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { if (content_type == GetTypeName(ContentSettingsType(type))) { int int_value = CONTENT_SETTING_DEFAULT; bool is_integer = i.value().GetAsInteger(&int_value); DCHECK(is_integer); (*value_map)[ContentSettingsType(type)].reset( - new base::FundamentalValue(int_value)); + ContentSettingToValue(IntToContentSetting(int_value)).release()); break; } } } - return make_scoped_ptr(value_map); + return value_map.Pass(); } void DefaultProvider::MigrateDefaultSettings() { @@ -512,7 +503,7 @@ scoped_ptr<DefaultProvider::ValueMap> value_map = ReadDictionaryPref(); - for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { ContentSettingsType content_type = ContentSettingsType(i); WriteIndividualPref(content_type, (*value_map)[content_type].get()); }
diff --git a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h index 3489395..09cac65 100644 --- a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h +++ b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h
@@ -9,8 +9,7 @@ #include <string> #include "base/memory/linked_ptr.h" -#include "components/content_settings/core/common/content_settings_pattern.h" -#include "components/content_settings/core/common/content_settings_types.h" +#include "components/content_settings/core/common/content_settings.h" class GURL; @@ -25,7 +24,6 @@ class OriginIdentifierValueMap { public: - typedef std::string ResourceIdentifier; struct EntryMapKey { ContentSettingsType content_type; ResourceIdentifier resource_identifier;
diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc index 445a4ad..8c65dbd 100644 --- a/components/content_settings/core/browser/content_settings_policy_provider.cc +++ b/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -284,10 +284,8 @@ ContentSettingsPattern secondary_pattern = !pattern_pair.second.IsValid() ? ContentSettingsPattern::Wildcard() : pattern_pair.second; - value_map->SetValue(pattern_pair.first, - secondary_pattern, - content_type, - NO_RESOURCE_IDENTIFIER, + value_map->SetValue(pattern_pair.first, secondary_pattern, content_type, + ResourceIdentifier(), new base::FundamentalValue( kPrefsForManagedContentSettingsMap[i].setting)); }
diff --git a/components/content_settings/core/browser/content_settings_provider.h b/components/content_settings/core/browser/content_settings_provider.h index a51ed52..c3e63e77 100644 --- a/components/content_settings/core/browser/content_settings_provider.h +++ b/components/content_settings/core/browser/content_settings_provider.h
@@ -7,12 +7,10 @@ #ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_PROVIDER_H_ #define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_PROVIDER_H_ -#define NO_RESOURCE_IDENTIFIER std::string() - #include <string> #include "base/values.h" -#include "components/content_settings/core/common/content_settings_types.h" +#include "components/content_settings/core/common/content_settings.h" class ContentSettingsPattern; @@ -21,8 +19,6 @@ struct Rule; class RuleIterator; -typedef std::string ResourceIdentifier; - class ProviderInterface { public: virtual ~ProviderInterface() {}
diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc index c8dfe50b..a67bb7d 100644 --- a/components/content_settings/core/browser/content_settings_utils.cc +++ b/components/content_settings/core/browser/content_settings_utils.cc
@@ -169,6 +169,14 @@ return *setting != CONTENT_SETTING_DEFAULT; } +scoped_ptr<base::Value> ContentSettingToValue(ContentSetting setting) { + if (setting <= CONTENT_SETTING_DEFAULT || + setting >= CONTENT_SETTING_NUM_SETTINGS) { + return nullptr; + } + return make_scoped_ptr(new base::FundamentalValue(setting)); +} + base::Value* GetContentSettingValueAndPatterns( const ProviderInterface* provider, const GURL& primary_url,
diff --git a/components/content_settings/core/browser/content_settings_utils.h b/components/content_settings/core/browser/content_settings_utils.h index 03861991..26efe6b 100644 --- a/components/content_settings/core/browser/content_settings_utils.h +++ b/components/content_settings/core/browser/content_settings_utils.h
@@ -9,6 +9,7 @@ #include <utility> #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -59,6 +60,10 @@ ContentSettingsPattern* primary_pattern, ContentSettingsPattern* secondary_pattern); +// Returns a |base::Value*| representation of |setting| if |setting| is +// a valid content setting. Otherwise, returns a nullptr. +scoped_ptr<base::Value> ContentSettingToValue(ContentSetting setting); + base::Value* GetContentSettingValueAndPatterns( const ProviderInterface* provider, const GURL& primary_url,
diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h index 7745ac1..c7264476 100644 --- a/components/content_settings/core/common/content_settings.h +++ b/components/content_settings/core/common/content_settings.h
@@ -62,6 +62,8 @@ namespace content_settings { +typedef std::string ResourceIdentifier; + // Enum containing the various source for content settings. Settings can be // set by policy, extension, the user or by the custodian of a supervised user. // Certain (internal) schemes are whilelisted. For whilelisted schemes the
diff --git a/components/content_settings/core/common/content_settings_pattern_unittest.cc b/components/content_settings/core/common/content_settings_pattern_unittest.cc index 3688d84..3fb0448 100644 --- a/components/content_settings/core/common/content_settings_pattern_unittest.cc +++ b/components/content_settings/core/common/content_settings_pattern_unittest.cc
@@ -555,6 +555,7 @@ EXPECT_EQ(ContentSettingsPattern::SUCCESSOR, Pattern("[*.]google.com").Compare( Pattern("mail.google.com"))); + EXPECT_TRUE(Pattern("mail.google.com") > Pattern("[*.]google.com")); EXPECT_EQ(ContentSettingsPattern::PREDECESSOR, Pattern("[*.]mail.google.com").Compare( @@ -562,6 +563,7 @@ EXPECT_EQ(ContentSettingsPattern::SUCCESSOR, Pattern("[*.]google.com").Compare( Pattern("[*.]mail.google.com"))); + EXPECT_TRUE(Pattern("[*.]mail.google.com") > Pattern("[*.]google.com")); EXPECT_EQ(ContentSettingsPattern::PREDECESSOR, Pattern("mail.google.com:80").Compare( @@ -569,6 +571,7 @@ EXPECT_EQ(ContentSettingsPattern::SUCCESSOR, Pattern("mail.google.com:*").Compare( Pattern("mail.google.com:80"))); + EXPECT_TRUE(Pattern("mail.google.com:80") > Pattern("mail.google.com:*")); EXPECT_EQ(ContentSettingsPattern::PREDECESSOR, Pattern("https://mail.google.com:*").Compare(
diff --git a/components/crash/app/BUILD.gn b/components/crash/app/BUILD.gn index 8c583bb..a758416 100644 --- a/components/crash/app/BUILD.gn +++ b/components/crash/app/BUILD.gn
@@ -45,6 +45,7 @@ deps = [ "//base", + "//base:base_static", ":lib", ]
diff --git a/components/cronet/DEPS b/components/cronet/DEPS index 8fa9d48..413c4b4 100644 --- a/components/cronet/DEPS +++ b/components/cronet/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+components/metrics", "+net", ]
diff --git a/components/cronet/android/cronet_histogram_manager.cc b/components/cronet/android/cronet_histogram_manager.cc index 8c30bbb..de1989b 100644 --- a/components/cronet/android/cronet_histogram_manager.cc +++ b/components/cronet/android/cronet_histogram_manager.cc
@@ -9,7 +9,7 @@ #include "base/android/jni_array.h" #include "base/metrics/statistics_recorder.h" -#include "components/metrics/histogram_manager.h" +#include "components/cronet/histogram_manager.h" #include "jni/CronetHistogramManager_jni.h" @@ -26,7 +26,7 @@ static jbyteArray GetHistogramDeltas(JNIEnv* env, jobject jcaller) { std::vector<uint8> data; - if (!metrics::HistogramManager::GetInstance()->GetDeltas(&data)) + if (!HistogramManager::GetInstance()->GetDeltas(&data)) return NULL; return base::android::ToJavaByteArray(env, &data[0], data.size()).Release(); }
diff --git a/components/cronet/cronet_static.gypi b/components/cronet/cronet_static.gypi index e4d688a..9edf982 100644 --- a/components/cronet/cronet_static.gypi +++ b/components/cronet/cronet_static.gypi
@@ -39,6 +39,8 @@ 'android/url_request_context_adapter.h', 'android/wrapped_channel_upload_element_reader.cc', 'android/wrapped_channel_upload_element_reader.h', + 'histogram_manager.cc', + 'histogram_manager.h', 'url_request_context_config.cc', 'url_request_context_config.h', 'url_request_context_config_list.h',
diff --git a/components/metrics/histogram_manager.cc b/components/cronet/histogram_manager.cc similarity index 95% rename from components/metrics/histogram_manager.cc rename to components/cronet/histogram_manager.cc index dfa865b..afbb447 100644 --- a/components/metrics/histogram_manager.cc +++ b/components/cronet/histogram_manager.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/metrics/histogram_manager.h" +#include "components/cronet/histogram_manager.h" #include <string> #include <vector> @@ -12,7 +12,7 @@ #include "base/metrics/histogram_samples.h" #include "components/metrics/histogram_encoder.h" -namespace metrics { +namespace cronet { // TODO(rtenneti): move g_histogram_manager into java code. static base::LazyInstance<HistogramManager>::Leaky @@ -64,4 +64,4 @@ return false; } -} // namespace metrics +} // namespace cronet
diff --git a/components/metrics/histogram_manager.h b/components/cronet/histogram_manager.h similarity index 77% rename from components/metrics/histogram_manager.h rename to components/cronet/histogram_manager.h index 7334ae3..ae4b249 100644 --- a/components/metrics/histogram_manager.h +++ b/components/cronet/histogram_manager.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_METRICS_HISTOGRAM_MANAGER_H_ -#define COMPONENTS_METRICS_HISTOGRAM_MANAGER_H_ +#ifndef COMPONENTS_CRONET_HISTOGRAM_MANAGER_H_ +#define COMPONENTS_CRONET_HISTOGRAM_MANAGER_H_ #include <string> #include <vector> @@ -16,14 +16,11 @@ #include "base/metrics/histogram_snapshot_manager.h" #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" -namespace metrics { +namespace cronet { -// TODO(mef): crbug.com/441441. Move components/metrics/histogram_manager.* -// files into components/android/cronet. -// -// A HistogramManager instance is created by Android. It is the central -// controller for the acquisition of log data, and the automatic transmission of -// that log data to an external server. +// A HistogramManager instance is created by the app. It is the central +// controller for the acquisition of log data, and recording deltas for +// transmission to an external server. class HistogramManager : public base::HistogramFlattener { public: HistogramManager(); @@ -57,6 +54,6 @@ DISALLOW_COPY_AND_ASSIGN(HistogramManager); }; -} // namespace metrics +} // namespace cronet -#endif // COMPONENTS_METRICS_HISTOGRAM_MANAGER_H_ +#endif // COMPONENTS_CRONET_HISTOGRAM_MANAGER_H_
diff --git a/components/metrics/histogram_manager_unittest.cc b/components/cronet/histogram_manager_unittest.cc similarity index 84% rename from components/metrics/histogram_manager_unittest.cc rename to components/cronet/histogram_manager_unittest.cc index 5e5f992..62f7b918 100644 --- a/components/metrics/histogram_manager_unittest.cc +++ b/components/cronet/histogram_manager_unittest.cc
@@ -2,19 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/metrics/histogram_manager.h" +#include "components/cronet/histogram_manager.h" #include <string> #include "base/basictypes.h" +#include "base/metrics/statistics_recorder.h" #include "testing/gtest/include/gtest/gtest.h" -namespace metrics { +namespace cronet { -// TODO(mef): crbug.com/441441. Move components/metrics/histogram_manager.* -// files into components/android/cronet. -// TODO(rtenneti): enable flaky HistogramBucketFields unit test. -TEST(HistogramManager, DISABLED_HistogramBucketFields) { +using metrics::ChromeUserMetricsExtension; +using metrics::HistogramEventProto; + +TEST(HistogramManager, HistogramBucketFields) { + base::StatisticsRecorder::Initialize(); // Capture histograms at the start of the test to avoid later GetDeltas() // calls picking them up. std::vector<uint8> data_init; @@ -55,4 +57,4 @@ EXPECT_EQ(1, histogram_proto2.bucket(0).count()); } -} // namespace metrics +} // namespace cronet
diff --git a/components/data_reduction_proxy/core/browser/BUILD.gn b/components/data_reduction_proxy/core/browser/BUILD.gn index 5330d25..0f0489e 100644 --- a/components/data_reduction_proxy/core/browser/BUILD.gn +++ b/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -91,10 +91,12 @@ sources = [ "data_reduction_proxy_bypass_protocol_unittest.cc", "data_reduction_proxy_bypass_stats_unittest.cc", + "data_reduction_proxy_compression_stats_unittest.cc", "data_reduction_proxy_config_service_client_unittest.cc", "data_reduction_proxy_config_unittest.cc", "data_reduction_proxy_configurator_unittest.cc", "data_reduction_proxy_interceptor_unittest.cc", + "data_reduction_proxy_io_data_unittest.cc", "data_reduction_proxy_metrics_unittest.cc", "data_reduction_proxy_network_delegate_unittest.cc", "data_reduction_proxy_prefs_unittest.cc",
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc index 6e56240..1753b38 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -120,8 +120,7 @@ context_->set_http_user_agent_settings(&http_user_agent_settings_); bypass_stats_.reset(new DataReductionProxyBypassStats( test_context_->config(), - test_context_->unreachable_callback(), - test_context_->task_runner())); + test_context_->unreachable_callback())); DataReductionProxyInterceptor* interceptor = new DataReductionProxyInterceptor(test_context_->config(),
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc index cd4ce09..87e94d2 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -4,12 +4,10 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h" -#include "base/bind.h" #include "base/callback.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" #include "base/prefs/pref_member.h" -#include "base/single_thread_task_runner.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_tamper_detection.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" @@ -104,28 +102,24 @@ DataReductionProxyBypassStats::DataReductionProxyBypassStats( DataReductionProxyConfig* config, - UnreachableCallback unreachable_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) + UnreachableCallback unreachable_callback) : data_reduction_proxy_config_(config), unreachable_callback_(unreachable_callback), last_bypass_type_(BYPASS_EVENT_TYPE_MAX), triggering_request_(true), - ui_task_runner_(ui_task_runner), successful_requests_through_proxy_count_(0), proxy_net_errors_count_(0), unavailable_(false) { DCHECK(config); NetworkChangeNotifier::AddNetworkChangeObserver(this); -}; +} DataReductionProxyBypassStats::~DataReductionProxyBypassStats() { NetworkChangeNotifier::RemoveNetworkChangeObserver(this); -}; +} void DataReductionProxyBypassStats::OnUrlRequestCompleted( const net::URLRequest* request, bool started) { - DCHECK(thread_checker_.CalledOnValidThread()); - DataReductionProxyTypeInfo proxy_info; // Ignore requests that did not use the data reduction proxy. The check for // LOAD_BYPASS_PROXY is necessary because the proxy_server() in the |request| @@ -369,12 +363,10 @@ void DataReductionProxyBypassStats::OnNetworkChanged( NetworkChangeNotifier::ConnectionType type) { - DCHECK(thread_checker_.CalledOnValidThread()); ClearRequestCounts(); } void DataReductionProxyBypassStats::ClearRequestCounts() { - DCHECK(thread_checker_.CalledOnValidThread()); successful_requests_through_proxy_count_ = 0; proxy_net_errors_count_ = 0; } @@ -385,18 +377,8 @@ (proxy_net_errors_count_ >= kMinFailedRequestsWhenUnavailable && successful_requests_through_proxy_count_ <= kMaxSuccessfulRequestsWhenUnavailable); - if (prev_unavailable != unavailable_) { - ui_task_runner_->PostTask(FROM_HERE, base::Bind( - &DataReductionProxyBypassStats::NotifyUnavailabilityOnUIThread, - base::Unretained(this), - unavailable_)); - } -} - -void DataReductionProxyBypassStats::NotifyUnavailabilityOnUIThread( - bool unavailable) { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - unreachable_callback_.Run(unavailable); + if (prev_unavailable != unavailable_) + unreachable_callback_.Run(unavailable_); } void DataReductionProxyBypassStats::RecordBypassedBytes(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h index 08a7930..efff8d11 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h
@@ -7,8 +7,6 @@ #include "base/callback.h" #include "base/prefs/pref_member.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "net/base/host_port_pair.h" #include "net/base/network_change_notifier.h" @@ -45,14 +43,12 @@ bool is_primary, const net::HttpResponseHeaders* headers); - // |params| outlives this class instance. |unreachable_callback| provides a - // hook to inform the user that the Data Reduction Proxy is unreachable, which - // occurs on the UI thread, hence the |ui_task_runner|. + // |config| outlives this class instance. |unreachable_callback| provides a + // hook to inform the user that the Data Reduction Proxy is unreachable. // |config| must not be null. DataReductionProxyBypassStats( DataReductionProxyConfig* config, - UnreachableCallback unreachable_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); + UnreachableCallback unreachable_callback); ~DataReductionProxyBypassStats() override; @@ -145,7 +141,6 @@ DataReductionProxyBypassType last_bypass_type_; // True if the last request triggered the current bypass. bool triggering_request_; - const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; // The following 2 fields are used to determine if data reduction proxy is // unreachable. We keep a count of requests which should go through @@ -163,8 +158,6 @@ // Whether or not the data reduction proxy is unavailable. bool unavailable_; - base::ThreadChecker thread_checker_; - DISALLOW_COPY_AND_ASSIGN(DataReductionProxyBypassStats); };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc index c0a4741..cc1930e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -114,8 +114,7 @@ return make_scoped_ptr( new DataReductionProxyBypassStats( test_context_->config(), - test_context_->unreachable_callback(), - test_context_->task_runner())).Pass(); + test_context_->unreachable_callback())); } net::URLRequest* url_request() {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc index c547e44..badf953 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -4,10 +4,14 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" +#include <vector> + +#include "base/basictypes.h" #include "base/bind.h" #include "base/command_line.h" #include "base/location.h" #include "base/logging.h" +#include "base/metrics/histogram.h" #include "base/prefs/pref_change_registrar.h" #include "base/prefs/pref_service.h" #include "base/prefs/scoped_user_pref_update.h" @@ -15,10 +19,287 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "base/values.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" namespace data_reduction_proxy { +namespace { + +// Returns the value at |index| of |list_value| as an int64. +int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) { + int64 val = 0; + std::string pref_value; + bool rv = list_value.GetString(index, &pref_value); + DCHECK(rv); + if (rv) { + rv = base::StringToInt64(pref_value, &val); + DCHECK(rv); + } + return val; +} + +// Ensure list has exactly |length| elements, either by truncating at the +// front, or appending "0"'s to the back. +void MaintainContentLengthPrefsWindow(base::ListValue* list, size_t length) { + // Remove data for old days from the front. + while (list->GetSize() > length) + list->Remove(0, NULL); + // Newly added lists are empty. Add entries to back to fill the window, + // each initialized to zero. + while (list->GetSize() < length) + list->AppendString(base::Int64ToString(0)); + DCHECK_EQ(length, list->GetSize()); +} + +// Increments an int64, stored as a string, in a ListPref at the specified +// index. The value must already exist and be a string representation of a +// number. +void AddInt64ToListPref(size_t index, + int64 length, + base::ListValue* list_update) { + int64 value = 0; + std::string old_string_value; + bool rv = list_update->GetString(index, &old_string_value); + DCHECK(rv); + if (rv) { + rv = base::StringToInt64(old_string_value, &value); + DCHECK(rv); + } + value += length; + list_update->Set(index, new base::StringValue(base::Int64ToString(value))); +} + +int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) { + std::string string_value; + if (!list_update.GetString(index, &string_value)) { + NOTREACHED(); + return 0; + } + + int64 value = 0; + bool rv = base::StringToInt64(string_value, &value); + DCHECK(rv); + return value; +} + +// DailyContentLengthUpdate maintains a data saving pref. The pref is a list +// of |kNumDaysInHistory| elements of daily total content lengths for the past +// |kNumDaysInHistory| days. +void RecordDailyContentLengthHistograms( + int64 original_length, + int64 received_length, + int64 original_length_with_data_reduction_enabled, + int64 received_length_with_data_reduction_enabled, + int64 original_length_via_data_reduction_proxy, + int64 received_length_via_data_reduction_proxy, + int64 https_length_with_data_reduction_enabled, + int64 short_bypass_length_with_data_reduction_enabled, + int64 long_bypass_length_with_data_reduction_enabled, + int64 unknown_length_with_data_reduction_enabled) { + // Report daily UMA only for days having received content. + if (original_length <= 0 || received_length <= 0) + return; + + // Record metrics in KB. + UMA_HISTOGRAM_COUNTS( + "Net.DailyOriginalContentLength", original_length >> 10); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength", received_length >> 10); + int percent = 0; + // UMA percentage cannot be negative. + if (original_length > received_length) { + percent = (100 * (original_length - received_length)) / original_length; + } + UMA_HISTOGRAM_PERCENTAGE("Net.DailyContentSavingPercent", percent); + + if (original_length_with_data_reduction_enabled <= 0 || + received_length_with_data_reduction_enabled <= 0) { + return; + } + + UMA_HISTOGRAM_COUNTS( + "Net.DailyOriginalContentLength_DataReductionProxyEnabled", + original_length_with_data_reduction_enabled >> 10); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength_DataReductionProxyEnabled", + received_length_with_data_reduction_enabled >> 10); + + int percent_data_reduction_proxy_enabled = 0; + // UMA percentage cannot be negative. + if (original_length_with_data_reduction_enabled > + received_length_with_data_reduction_enabled) { + percent_data_reduction_proxy_enabled = + 100 * (original_length_with_data_reduction_enabled - + received_length_with_data_reduction_enabled) / + original_length_with_data_reduction_enabled; + } + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentSavingPercent_DataReductionProxyEnabled", + percent_data_reduction_proxy_enabled); + + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentPercent_DataReductionProxyEnabled", + (100 * received_length_with_data_reduction_enabled) / received_length); + + DCHECK_GE(https_length_with_data_reduction_enabled, 0); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength_DataReductionProxyEnabled_Https", + https_length_with_data_reduction_enabled >> 10); + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentPercent_DataReductionProxyEnabled_Https", + (100 * https_length_with_data_reduction_enabled) / received_length); + + DCHECK_GE(short_bypass_length_with_data_reduction_enabled, 0); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength_DataReductionProxyEnabled_ShortBypass", + short_bypass_length_with_data_reduction_enabled >> 10); + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentPercent_DataReductionProxyEnabled_ShortBypass", + ((100 * short_bypass_length_with_data_reduction_enabled) / + received_length)); + + DCHECK_GE(long_bypass_length_with_data_reduction_enabled, 0); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength_DataReductionProxyEnabled_LongBypass", + long_bypass_length_with_data_reduction_enabled >> 10); + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentPercent_DataReductionProxyEnabled_LongBypass", + ((100 * long_bypass_length_with_data_reduction_enabled) / + received_length)); + + DCHECK_GE(unknown_length_with_data_reduction_enabled, 0); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength_DataReductionProxyEnabled_Unknown", + unknown_length_with_data_reduction_enabled >> 10); + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentPercent_DataReductionProxyEnabled_Unknown", + ((100 * unknown_length_with_data_reduction_enabled) / + received_length)); + + DCHECK_GE(original_length_via_data_reduction_proxy, 0); + UMA_HISTOGRAM_COUNTS( + "Net.DailyOriginalContentLength_ViaDataReductionProxy", + original_length_via_data_reduction_proxy >> 10); + DCHECK_GE(received_length_via_data_reduction_proxy, 0); + UMA_HISTOGRAM_COUNTS( + "Net.DailyContentLength_ViaDataReductionProxy", + received_length_via_data_reduction_proxy >> 10); + int percent_via_data_reduction_proxy = 0; + if (original_length_via_data_reduction_proxy > + received_length_via_data_reduction_proxy) { + percent_via_data_reduction_proxy = + 100 * (original_length_via_data_reduction_proxy - + received_length_via_data_reduction_proxy) / + original_length_via_data_reduction_proxy; + } + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentSavingPercent_ViaDataReductionProxy", + percent_via_data_reduction_proxy); + UMA_HISTOGRAM_PERCENTAGE( + "Net.DailyContentPercent_ViaDataReductionProxy", + (100 * received_length_via_data_reduction_proxy) / received_length); +} + +class DailyContentLengthUpdate { + public: + DailyContentLengthUpdate(base::ListValue* update) + : update_(update) {} + + void UpdateForDataChange(int days_since_last_update) { + // New empty lists may have been created. Maintain the invariant that + // there should be exactly |kNumDaysInHistory| days in the histories. + MaintainContentLengthPrefsWindow(update_, kNumDaysInHistory); + if (days_since_last_update) { + MaintainContentLengthPrefForDateChange(days_since_last_update); + } + } + + // Update the lengths for the current day. + void Add(int content_length) { + AddInt64ToListPref(kNumDaysInHistory - 1, content_length, update_); + } + + int64 GetListPrefValue(size_t index) { + return ListPrefInt64Value(*update_, index); + } + + private: + // Update the list for date change and ensure the list has exactly |length| + // elements. The last entry in the list will be for the current day after + // the update. + void MaintainContentLengthPrefForDateChange(int days_since_last_update) { + if (days_since_last_update == -1) { + // The system may go backwards in time by up to a day for legitimate + // reasons, such as with changes to the time zone. In such cases, we + // keep adding to the current day. + // Note: we accept the fact that some reported data is shifted to + // the adjacent day if users travel back and forth across time zones. + days_since_last_update = 0; + } else if (days_since_last_update < -1) { + // Erase all entries if the system went backwards in time by more than + // a day. + update_->Clear(); + + days_since_last_update = kNumDaysInHistory; + } + DCHECK_GE(days_since_last_update, 0); + + // Add entries for days since last update event. This will make the + // lists longer than kNumDaysInHistory. The additional items will be cut off + // from the head of the lists by |MaintainContentLengthPrefsWindow|, below. + for (int i = 0; + i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory); + ++i) { + update_->AppendString(base::Int64ToString(0)); + } + + // Entries for new days may have been appended. Maintain the invariant that + // there should be exactly |kNumDaysInHistory| days in the histories. + MaintainContentLengthPrefsWindow(update_, kNumDaysInHistory); + } + + base::ListValue* update_; +}; + +// DailyDataSavingUpdate maintains a pair of data saving prefs, original_update_ +// and received_update_. pref_original is a list of |kNumDaysInHistory| elements +// of daily total original content lengths for the past |kNumDaysInHistory| +// days. pref_received is the corresponding list of the daily total received +// content lengths. +class DailyDataSavingUpdate { + public: + DailyDataSavingUpdate(base::ListValue* original, + base::ListValue* received) + : original_(original), + received_(received) {} + + void UpdateForDataChange(int days_since_last_update) { + original_.UpdateForDataChange(days_since_last_update); + received_.UpdateForDataChange(days_since_last_update); + } + + // Update the lengths for the current day. + void Add(int original_content_length, int received_content_length) { + original_.Add(original_content_length); + received_.Add(received_content_length); + } + + int64 GetOriginalListPrefValue(size_t index) { + return original_.GetListPrefValue(index); + } + int64 GetReceivedListPrefValue(size_t index) { + return received_.GetListPrefValue(index); + } + + private: + DailyContentLengthUpdate original_; + DailyContentLengthUpdate received_; +}; + +// Report UMA metrics for daily data reductions. +} // namespace + DataReductionProxyCompressionStats::DataReductionProxyCompressionStats( PrefService* prefs, scoped_refptr<base::SequencedTaskRunner> task_runner, @@ -73,7 +354,7 @@ pref_change_registrar_->Init(pref_service_); pref_change_registrar_->Add(prefs::kUpdateDailyReceivedContentLengths, base::Bind(&DataReductionProxyCompressionStats::OnUpdateContentLengths, - GetWeakPtr())); + weak_factory_.GetWeakPtr())); } void DataReductionProxyCompressionStats::OnUpdateContentLengths() { @@ -85,6 +366,31 @@ pref_service_->SetBoolean(prefs::kUpdateDailyReceivedContentLengths, false); } +void DataReductionProxyCompressionStats::UpdateContentLengths( + int received_content_length, + int original_content_length, + bool data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type) { + DCHECK(thread_checker_.CalledOnValidThread()); + int64 total_received = GetInt64( + data_reduction_proxy::prefs::kHttpReceivedContentLength); + int64 total_original = GetInt64( + data_reduction_proxy::prefs::kHttpOriginalContentLength); + total_received += received_content_length; + total_original += original_content_length; + SetInt64(data_reduction_proxy::prefs::kHttpReceivedContentLength, + total_received); + SetInt64(data_reduction_proxy::prefs::kHttpOriginalContentLength, + total_original); + + RecordContentLengthPrefs( + received_content_length, + original_content_length, + data_reduction_proxy_enabled, + request_type, + base::Time::Now()); +} + void DataReductionProxyCompressionStats::InitInt64Pref(const char* pref) { int64 pref_value = pref_service_->GetInt64(pref); pref_map_[pref] = pref_value; @@ -158,6 +464,70 @@ return dict; } +int64 DataReductionProxyCompressionStats::GetLastUpdateTime() { + int64 last_update_internal = GetInt64( + prefs::kDailyHttpContentLengthLastUpdateDate); + base::Time last_update = base::Time::FromInternalValue(last_update_internal); + return static_cast<int64>(last_update.ToJsTime()); +} + +void DataReductionProxyCompressionStats::ResetStatistics() { + base::ListValue* original_update = + GetList(prefs::kDailyHttpOriginalContentLength); + base::ListValue* received_update = + GetList(prefs::kDailyHttpReceivedContentLength); + original_update->Clear(); + received_update->Clear(); + for (size_t i = 0; i < kNumDaysInHistory; ++i) { + original_update->AppendString(base::Int64ToString(0)); + received_update->AppendString(base::Int64ToString(0)); + } +} + +ContentLengthList DataReductionProxyCompressionStats::GetDailyContentLengths( + const char* pref_name) { + ContentLengthList content_lengths; + const base::ListValue* list_value = GetList(pref_name); + if (list_value->GetSize() == kNumDaysInHistory) { + for (size_t i = 0; i < kNumDaysInHistory; ++i) + content_lengths.push_back(GetInt64PrefValue(*list_value, i)); + } + return content_lengths; +} + +void DataReductionProxyCompressionStats::GetContentLengths( + unsigned int days, + int64* original_content_length, + int64* received_content_length, + int64* last_update_time) { + DCHECK_LE(days, kNumDaysInHistory); + + const base::ListValue* original_list = + GetList(prefs::kDailyHttpOriginalContentLength); + const base::ListValue* received_list = + GetList(prefs::kDailyHttpReceivedContentLength); + + if (original_list->GetSize() != kNumDaysInHistory || + received_list->GetSize() != kNumDaysInHistory) { + *original_content_length = 0L; + *received_content_length = 0L; + *last_update_time = 0L; + return; + } + + int64 orig = 0L; + int64 recv = 0L; + // Include days from the end of the list going backwards. + for (size_t i = kNumDaysInHistory - days; + i < kNumDaysInHistory; ++i) { + orig += GetInt64PrefValue(*original_list, i); + recv += GetInt64PrefValue(*received_list, i); + } + *original_content_length = orig; + *received_content_length = recv; + *last_update_time = GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate); +} + void DataReductionProxyCompressionStats::ClearDataSavingStatistics() { list_pref_map_.get( prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled)->Clear(); @@ -191,7 +561,8 @@ task_runner_->PostDelayedTask( FROM_HERE, - base::Bind(&DataReductionProxyCompressionStats::WritePrefs, GetWeakPtr()), + base::Bind(&DataReductionProxyCompressionStats::WritePrefs, + weak_factory_.GetWeakPtr()), delay_); delayed_task_posted_ = true; @@ -222,9 +593,132 @@ return value; } -base::WeakPtr<DataReductionProxyCompressionStats> -DataReductionProxyCompressionStats::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); +void DataReductionProxyCompressionStats::RecordContentLengthPrefs( + int received_content_length, + int original_content_length, + bool with_data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type, + base::Time now) { + // TODO(bengr): Remove this check once the underlying cause of + // http://crbug.com/287821 is fixed. For now, only continue if the current + // year is reported as being between 1972 and 2970. + base::TimeDelta time_since_unix_epoch = now - base::Time::UnixEpoch(); + const int kMinDaysSinceUnixEpoch = 365 * 2; // 2 years. + const int kMaxDaysSinceUnixEpoch = 365 * 1000; // 1000 years. + if (time_since_unix_epoch.InDays() < kMinDaysSinceUnixEpoch || + time_since_unix_epoch.InDays() > kMaxDaysSinceUnixEpoch) { + return; + } + + // Determine how many days it has been since the last update. + int64 then_internal = GetInt64( + data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate); + + // Local midnight could have been shifted due to time zone change. + // If time is null then don't care if midnight will be wrong shifted due to + // time zone change because it's still too much time ago. + base::Time then_midnight = base::Time::FromInternalValue(then_internal); + if (!then_midnight.is_null()) { + then_midnight = then_midnight.LocalMidnight(); + } + base::Time midnight = now.LocalMidnight(); + + int days_since_last_update = (midnight - then_midnight).InDays(); + + // Each day, we calculate the total number of bytes received and the total + // size of all corresponding resources before any data-reducing recompression + // is applied. These values are used to compute the data savings realized + // by applying our compression techniques. Totals for the last + // |kNumDaysInHistory| days are maintained. + DailyDataSavingUpdate total( + GetList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength), + GetList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength)); + total.UpdateForDataChange(days_since_last_update); + + DailyDataSavingUpdate proxy_enabled( + GetList(data_reduction_proxy::prefs:: + kDailyOriginalContentLengthWithDataReductionProxyEnabled), + GetList(data_reduction_proxy::prefs:: + kDailyContentLengthWithDataReductionProxyEnabled)); + proxy_enabled.UpdateForDataChange(days_since_last_update); + + DailyDataSavingUpdate via_proxy( + GetList(data_reduction_proxy::prefs:: + kDailyOriginalContentLengthViaDataReductionProxy), + GetList(data_reduction_proxy::prefs:: + kDailyContentLengthViaDataReductionProxy)); + via_proxy.UpdateForDataChange(days_since_last_update); + + DailyContentLengthUpdate https( + GetList(data_reduction_proxy::prefs:: + kDailyContentLengthHttpsWithDataReductionProxyEnabled)); + https.UpdateForDataChange(days_since_last_update); + + DailyContentLengthUpdate short_bypass( + GetList(data_reduction_proxy::prefs:: + kDailyContentLengthShortBypassWithDataReductionProxyEnabled)); + short_bypass.UpdateForDataChange(days_since_last_update); + + DailyContentLengthUpdate long_bypass( + GetList(data_reduction_proxy::prefs:: + kDailyContentLengthLongBypassWithDataReductionProxyEnabled)); + long_bypass.UpdateForDataChange(days_since_last_update); + + DailyContentLengthUpdate unknown( + GetList(data_reduction_proxy::prefs:: + kDailyContentLengthUnknownWithDataReductionProxyEnabled)); + unknown.UpdateForDataChange(days_since_last_update); + + total.Add(original_content_length, received_content_length); + if (with_data_reduction_proxy_enabled) { + proxy_enabled.Add(original_content_length, received_content_length); + // Ignore data source cases, if exist, when + // "with_data_reduction_proxy_enabled == false" + switch (request_type) { + case VIA_DATA_REDUCTION_PROXY: + via_proxy.Add(original_content_length, received_content_length); + break; + case HTTPS: + https.Add(received_content_length); + break; + case SHORT_BYPASS: + short_bypass.Add(received_content_length); + break; + case LONG_BYPASS: + long_bypass.Add(received_content_length); + break; + case UNKNOWN_TYPE: + unknown.Add(received_content_length); + break; + } + } + + if (days_since_last_update) { + // Record the last update time in microseconds in UTC. + SetInt64( + data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate, + midnight.ToInternalValue()); + + // A new day. Report the previous day's data if exists. We'll lose usage + // data if the last time Chrome was run was more than a day ago. + // Here, we prefer collecting less data but the collected data is + // associated with an accurate date. + if (days_since_last_update == 1) { + // The previous day's data point is the second one from the tail. + // Therefore (kNumDaysInHistory - 2) below. + RecordDailyContentLengthHistograms( + total.GetOriginalListPrefValue(kNumDaysInHistory - 2), + total.GetReceivedListPrefValue(kNumDaysInHistory - 2), + proxy_enabled.GetOriginalListPrefValue(kNumDaysInHistory - 2), + proxy_enabled.GetReceivedListPrefValue(kNumDaysInHistory - 2), + via_proxy.GetOriginalListPrefValue(kNumDaysInHistory - 2), + via_proxy.GetReceivedListPrefValue(kNumDaysInHistory - 2), + https.GetListPrefValue(kNumDaysInHistory - 2), + short_bypass.GetListPrefValue(kNumDaysInHistory - 2), + long_bypass.GetListPrefValue(kNumDaysInHistory - 2), + unknown.GetListPrefValue(kNumDaysInHistory - 2)); + } + } } } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h index 1990295..297f810 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
@@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" class PrefChangeRegistrar; @@ -44,10 +45,57 @@ const base::TimeDelta& delay); ~DataReductionProxyCompressionStats(); + // Records daily data savings statistics to prefs and reports data savings + // UMA. + void UpdateContentLengths(int received_content_length, + int original_content_length, + bool data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type); + + // Creates a |Value| summary of the persistent state of the network session. + // The caller is responsible for deleting the returned value. + // Must be called on the UI thread. + base::Value* HistoricNetworkStatsInfoToValue(); + + // Returns the time in milliseconds since epoch that the last update was made + // to the daily original and received content lengths. + int64 GetLastUpdateTime(); + + // Resets daily content length statistics. + void ResetStatistics(); + + // Clears all data saving statistics. + void ClearDataSavingStatistics(); + + // Returns a list of all the daily content lengths. + ContentLengthList GetDailyContentLengths(const char* pref_name); + + // Returns aggregate received and original content lengths over the specified + // number of days, as well as the time these stats were last updated. + void GetContentLengths(unsigned int days, + int64* original_content_length, + int64* received_content_length, + int64* last_update_time); + + private: + friend class DataReductionProxyCompressionStatsTest; + + typedef std::map<const char*, int64> DataReductionProxyPrefMap; + typedef base::ScopedPtrHashMap<const char*, base::ListValue> + DataReductionProxyListPrefMap; + // Loads all data_reduction_proxy::prefs into the |pref_map_| and // |list_pref_map_|. void Init(); + // Gets the value of |pref| from the pref service and adds it to the + // |pref_map|. + void InitInt64Pref(const char* pref); + + // Gets the value of |pref| from the pref service and adds it to the + // |list_pref_map|. + void InitListPref(const char* pref); + void OnUpdateContentLengths(); // Gets the int64 pref at |pref_path| from the |DataReductionProxyPrefMap|. @@ -64,29 +112,6 @@ // |DataReductionProxyListPrefMap| to |pref_service|. void WritePrefs(); - // Creates a |Value| summary of the persistent state of the network session. - // The caller is responsible for deleting the returned value. - // Must be called on the UI thread. - base::Value* HistoricNetworkStatsInfoToValue(); - - // Clears all data saving statistics. - void ClearDataSavingStatistics(); - - base::WeakPtr<DataReductionProxyCompressionStats> GetWeakPtr(); - - private: - typedef std::map<const char*, int64> DataReductionProxyPrefMap; - typedef base::ScopedPtrHashMap<const char*, base::ListValue> - DataReductionProxyListPrefMap; - - // Gets the value of |pref| from the pref service and adds it to the - // |pref_map|. - void InitInt64Pref(const char* pref); - - // Gets the value of |pref| from the pref service and adds it to the - // |list_pref_map|. - void InitListPref(const char* pref); - // Writes the stored prefs to |pref_service| and then posts another a delayed // task to write prefs again in |kMinutesBetweenWrites|. void DelayedWritePrefs(); @@ -100,6 +125,14 @@ // index. int64 GetListPrefInt64Value(const base::ListValue& list_update, size_t index); + // Records content length updates to prefs. + void RecordContentLengthPrefs( + int received_content_length, + int original_content_length, + bool with_data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type, + base::Time now); + PrefService* pref_service_; scoped_refptr<base::SequencedTaskRunner> task_runner_; const base::TimeDelta delay_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc index 6bdaba8..87e92e60 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats_unittest.cc
@@ -3,8 +3,10 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/prefs/pref_registry_simple.h" +#include "base/prefs/pref_service.h" #include "base/prefs/testing_pref_service.h" #include "base/strings/string_number_conversions.h" #include "base/test/test_simple_task_runner.h" @@ -18,8 +20,6 @@ namespace { -// TODO Make kNumDaysInHistory accessible from DataReductionProxySettings. -const size_t kNumDaysInHistory = 60; const int kWriteDelayMinutes = 60; int64 GetListPrefInt64Value( @@ -36,13 +36,42 @@ namespace data_reduction_proxy { +// The initial last update time used in test. There is no leap second a few +// days around this time used in the test. +// Note: No time zone is specified. Local time will be assumed by +// base::Time::FromString below. +const char kLastUpdateTime[] = "Wed, 18 Sep 2013 03:45:26"; + class DataReductionProxyCompressionStatsTest : public testing::Test { protected: DataReductionProxyCompressionStatsTest() : task_runner_(scoped_refptr<base::TestSimpleTaskRunner>( - new base::TestSimpleTaskRunner())) {} + new base::TestSimpleTaskRunner())) { + base::Time::FromString(kLastUpdateTime, &now_); + } - void SetUp() override { RegisterPrefs(simple_pref_service_.registry()); } + void SetUp() override { + compression_stats_.reset(new DataReductionProxyCompressionStats( + pref_service(), task_runner_, base::TimeDelta())); + RegisterSimpleProfilePrefs(pref_service()->registry()); + } + + void ResetCompressionStatsWithDelay(const base::TimeDelta& delay) { + compression_stats_.reset(new DataReductionProxyCompressionStats( + pref_service(), task_runner_, delay)); + } + + base::Time FakeNow() const { + return now_ + now_delta_; + } + + void SetFakeTimeDeltaInHours(int hours) { + now_delta_ = base::TimeDelta::FromHours(hours); + } + + void AddFakeTimeDeltaInHours(int hours) { + now_delta_ += base::TimeDelta::FromHours(hours); + } void SetUpPrefs() { CreatePrefList(prefs::kDailyHttpOriginalContentLength); @@ -86,7 +115,7 @@ // |simple_pref_service| for |pref|. void VerifyPrefListWasWritten(const char* pref) { const base::ListValue* delayed_list = compression_stats_->GetList(pref); - const base::ListValue* written_list = simple_pref_service_.GetList(pref); + const base::ListValue* written_list = pref_service()->GetList(pref); ASSERT_EQ(delayed_list->GetSize(), written_list->GetSize()); size_t count = delayed_list->GetSize(); @@ -100,7 +129,7 @@ // |simple_pref_service|. void VerifyPrefWasWritten(const char* pref) { int64 delayed_pref = compression_stats_->GetInt64(pref); - int64 written_pref = simple_pref_service_.GetInt64(pref); + int64 written_pref = pref_service()->GetInt64(pref); EXPECT_EQ(delayed_pref, written_pref); } @@ -123,16 +152,154 @@ EXPECT_EQ(service_pref, dict_pref); } + // Verify the pref list values are equal to the given values. + // If the count of values is less than kNumDaysInHistory, zeros are assumed + // at the beginning. + void VerifyPrefList(const char* pref, const int64* values, size_t count) { + ASSERT_GE(kNumDaysInHistory, count); + base::ListValue* update = compression_stats_->GetList(pref); + ASSERT_EQ(kNumDaysInHistory, update->GetSize()) << "Pref: " << pref; + + for (size_t i = 0; i < count; ++i) { + EXPECT_EQ( + values[i], + GetListPrefInt64Value(*update, kNumDaysInHistory - count + i)) + << "index=" << (kNumDaysInHistory - count + i); + } + for (size_t i = 0; i < kNumDaysInHistory - count; ++i) { + EXPECT_EQ(0, GetListPrefInt64Value(*update, i)) << "index=" << i; + } + } + + // Verify all daily data saving pref list values. + void VerifyDailyDataSavingContentLengthPrefLists( + const int64* original_values, size_t original_count, + const int64* received_values, size_t received_count, + const int64* original_with_data_reduction_proxy_enabled_values, + size_t original_with_data_reduction_proxy_enabled_count, + const int64* received_with_data_reduction_proxy_enabled_values, + size_t received_with_data_reduction_proxy_count, + const int64* original_via_data_reduction_proxy_values, + size_t original_via_data_reduction_proxy_count, + const int64* received_via_data_reduction_proxy_values, + size_t received_via_data_reduction_proxy_count) { + VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength, + original_values, original_count); + VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength, + received_values, received_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyOriginalContentLengthWithDataReductionProxyEnabled, + original_with_data_reduction_proxy_enabled_values, + original_with_data_reduction_proxy_enabled_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthWithDataReductionProxyEnabled, + received_with_data_reduction_proxy_enabled_values, + received_with_data_reduction_proxy_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyOriginalContentLengthViaDataReductionProxy, + original_via_data_reduction_proxy_values, + original_via_data_reduction_proxy_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthViaDataReductionProxy, + received_via_data_reduction_proxy_values, + received_via_data_reduction_proxy_count); + } + + // Verify daily data saving pref for request types. + void VerifyDailyRequestTypeContentLengthPrefLists( + const int64* original_values, size_t original_count, + const int64* received_values, size_t received_count, + const int64* original_with_data_reduction_proxy_enabled_values, + size_t original_with_data_reduction_proxy_enabled_count, + const int64* received_with_data_reduction_proxy_enabled_values, + size_t received_with_data_reduction_proxy_count, + const int64* https_with_data_reduction_proxy_enabled_values, + size_t https_with_data_reduction_proxy_enabled_count, + const int64* short_bypass_with_data_reduction_proxy_enabled_values, + size_t short_bypass_with_data_reduction_proxy_enabled_count, + const int64* long_bypass_with_data_reduction_proxy_enabled_values, + size_t long_bypass_with_data_reduction_proxy_enabled_count, + const int64* unknown_with_data_reduction_proxy_enabled_values, + size_t unknown_with_data_reduction_proxy_enabled_count) { + VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength, + original_values, original_count); + VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength, + received_values, received_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyOriginalContentLengthWithDataReductionProxyEnabled, + original_with_data_reduction_proxy_enabled_values, + original_with_data_reduction_proxy_enabled_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthWithDataReductionProxyEnabled, + received_with_data_reduction_proxy_enabled_values, + received_with_data_reduction_proxy_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthHttpsWithDataReductionProxyEnabled, + https_with_data_reduction_proxy_enabled_values, + https_with_data_reduction_proxy_enabled_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthShortBypassWithDataReductionProxyEnabled, + short_bypass_with_data_reduction_proxy_enabled_values, + short_bypass_with_data_reduction_proxy_enabled_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthLongBypassWithDataReductionProxyEnabled, + long_bypass_with_data_reduction_proxy_enabled_values, + long_bypass_with_data_reduction_proxy_enabled_count); + VerifyPrefList( + data_reduction_proxy::prefs:: + kDailyContentLengthUnknownWithDataReductionProxyEnabled, + unknown_with_data_reduction_proxy_enabled_values, + unknown_with_data_reduction_proxy_enabled_count); + } + + int64 GetInt64(const char* pref_path) { + return compression_stats_->GetInt64(pref_path); + } + + void SetInt64(const char* pref_path, int64 pref_value) { + compression_stats_->SetInt64(pref_path, pref_value); + } + + void RecordContentLengthPrefs(int received_content_length, + int original_content_length, + bool with_data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type, + base::Time now) { + compression_stats_->RecordContentLengthPrefs( + received_content_length, original_content_length, + with_data_reduction_proxy_enabled, request_type, now); + } + + DataReductionProxyCompressionStats* compression_stats() { + return compression_stats_.get(); + } + + void RunPendingTasks() { + task_runner_->RunPendingTasks(); + } + + TestingPrefServiceSimple* pref_service() { + return &simple_pref_service_; + } + + private: scoped_refptr<base::TestSimpleTaskRunner> task_runner_; TestingPrefServiceSimple simple_pref_service_; scoped_ptr<DataReductionProxyCompressionStats> compression_stats_; + base::Time now_; + base::TimeDelta now_delta_; }; TEST_F(DataReductionProxyCompressionStatsTest, WritePrefsDirect) { - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta())); SetUpPrefs(); VerifyPrefWasWritten(prefs::kHttpOriginalContentLength); @@ -142,13 +309,11 @@ } TEST_F(DataReductionProxyCompressionStatsTest, WritePrefsDelayed) { - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta::FromMinutes(kWriteDelayMinutes))); + ResetCompressionStatsWithDelay( + base::TimeDelta::FromMinutes(kWriteDelayMinutes)); SetUpPrefs(); - task_runner_->RunPendingTasks(); + RunPendingTasks(); VerifyPrefWasWritten(prefs::kHttpOriginalContentLength); VerifyPrefWasWritten(prefs::kHttpReceivedContentLength); @@ -158,13 +323,11 @@ TEST_F(DataReductionProxyCompressionStatsTest, WritePrefsOnUpdateDailyReceivedContentLengths) { - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta::FromMinutes(kWriteDelayMinutes))); + ResetCompressionStatsWithDelay( + base::TimeDelta::FromMinutes(kWriteDelayMinutes)); SetUpPrefs(); - simple_pref_service_.SetBoolean( + pref_service()->SetBoolean( prefs::kUpdateDailyReceivedContentLengths, true); VerifyPrefWasWritten(prefs::kHttpOriginalContentLength); @@ -177,23 +340,19 @@ HistoricNetworkStatsInfoToValue) { const int64 kOriginalLength = 150; const int64 kReceivedLength = 100; - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta::FromMinutes(kWriteDelayMinutes))); + ResetCompressionStatsWithDelay( + base::TimeDelta::FromMinutes(kWriteDelayMinutes)); base::DictionaryValue* dict = nullptr; scoped_ptr<base::Value> stats_value( - compression_stats_->HistoricNetworkStatsInfoToValue()); + compression_stats()->HistoricNetworkStatsInfoToValue()); EXPECT_TRUE(stats_value->GetAsDictionary(&dict)); VerifyPrefs(dict); - compression_stats_->SetInt64(prefs::kHttpOriginalContentLength, - kOriginalLength); - compression_stats_->SetInt64(prefs::kHttpReceivedContentLength, - kReceivedLength); + SetInt64(prefs::kHttpOriginalContentLength, kOriginalLength); + SetInt64(prefs::kHttpReceivedContentLength, kReceivedLength); - stats_value.reset(compression_stats_->HistoricNetworkStatsInfoToValue()); + stats_value.reset(compression_stats()->HistoricNetworkStatsInfoToValue()); EXPECT_TRUE(stats_value->GetAsDictionary(&dict)); VerifyPrefs(dict); } @@ -202,23 +361,17 @@ HistoricNetworkStatsInfoToValueDirect) { const int64 kOriginalLength = 150; const int64 kReceivedLength = 100; - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta())); base::DictionaryValue* dict = nullptr; scoped_ptr<base::Value> stats_value( - compression_stats_->HistoricNetworkStatsInfoToValue()); + compression_stats()->HistoricNetworkStatsInfoToValue()); EXPECT_TRUE(stats_value->GetAsDictionary(&dict)); VerifyPrefs(dict); - compression_stats_->SetInt64(prefs::kHttpOriginalContentLength, - kOriginalLength); - compression_stats_->SetInt64(prefs::kHttpReceivedContentLength, - kReceivedLength); + SetInt64(prefs::kHttpOriginalContentLength, kOriginalLength); + SetInt64(prefs::kHttpReceivedContentLength, kReceivedLength); - stats_value.reset(compression_stats_->HistoricNetworkStatsInfoToValue()); + stats_value.reset(compression_stats()->HistoricNetworkStatsInfoToValue()); EXPECT_TRUE(stats_value->GetAsDictionary(&dict)); VerifyPrefs(dict); } @@ -231,14 +384,12 @@ base::ListValue list_value; list_value.Insert(0, new base::StringValue(base::Int64ToString(1234))); - simple_pref_service_.Set(prefs::kDailyHttpOriginalContentLength, list_value); + pref_service()->Set(prefs::kDailyHttpOriginalContentLength, list_value); - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta::FromMinutes(kWriteDelayMinutes))); + ResetCompressionStatsWithDelay( + base::TimeDelta::FromMinutes(kWriteDelayMinutes)); - const base::ListValue* value = simple_pref_service_.GetList( + const base::ListValue* value = pref_service()->GetList( prefs::kDailyHttpOriginalContentLength); EXPECT_EQ(0u, value->GetSize()); } @@ -247,18 +398,421 @@ ClearPrefsOnRestartDisabled) { base::ListValue list_value; list_value.Insert(0, new base::StringValue(base::Int64ToString(1234))); - simple_pref_service_.Set(prefs::kDailyHttpOriginalContentLength, list_value); + pref_service()->Set(prefs::kDailyHttpOriginalContentLength, list_value); - compression_stats_.reset(new DataReductionProxyCompressionStats( - &simple_pref_service_, - task_runner_, - base::TimeDelta::FromMinutes(kWriteDelayMinutes))); + ResetCompressionStatsWithDelay( + base::TimeDelta::FromMinutes(kWriteDelayMinutes)); - const base::ListValue* value = simple_pref_service_.GetList( + const base::ListValue* value = pref_service()->GetList( prefs::kDailyHttpOriginalContentLength); std::string string_value; value->GetString(0, &string_value); EXPECT_EQ("1234", string_value); } +TEST_F(DataReductionProxyCompressionStatsTest, TotalLengths) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + + compression_stats()->UpdateContentLengths( + kReceivedLength, kOriginalLength, + pref_service()->GetBoolean( + data_reduction_proxy::prefs::kDataReductionProxyEnabled), + UNKNOWN_TYPE); + + EXPECT_EQ(kReceivedLength, + GetInt64(data_reduction_proxy::prefs::kHttpReceivedContentLength)); + EXPECT_FALSE(pref_service()->GetBoolean( + data_reduction_proxy::prefs::kDataReductionProxyEnabled)); + EXPECT_EQ(kOriginalLength, + GetInt64(data_reduction_proxy::prefs::kHttpOriginalContentLength)); + + // Record the same numbers again, and total lengths should be doubled. + compression_stats()->UpdateContentLengths( + kReceivedLength, kOriginalLength, + pref_service()->GetBoolean( + data_reduction_proxy::prefs::kDataReductionProxyEnabled), + UNKNOWN_TYPE); + + EXPECT_EQ(kReceivedLength * 2, + GetInt64(data_reduction_proxy::prefs::kHttpReceivedContentLength)); + EXPECT_FALSE(pref_service()->GetBoolean( + data_reduction_proxy::prefs::kDataReductionProxyEnabled)); + EXPECT_EQ(kOriginalLength * 2, + GetInt64(data_reduction_proxy::prefs::kHttpOriginalContentLength)); +} + +TEST_F(DataReductionProxyCompressionStatsTest, OneResponse) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + int64 original[] = {kOriginalLength}; + int64 received[] = {kReceivedLength}; + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original, 1, received, 1, + original, 1, received, 1); +} + +TEST_F(DataReductionProxyCompressionStatsTest, MultipleResponses) { + const int64 kOriginalLength = 150; + const int64 kReceivedLength = 100; + int64 original[] = {kOriginalLength}; + int64 received[] = {kReceivedLength}; + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, false, UNKNOWN_TYPE, FakeNow()); + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + NULL, 0, NULL, 0, NULL, 0, NULL, 0); + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, UNKNOWN_TYPE, FakeNow()); + original[0] += kOriginalLength; + received[0] += kReceivedLength; + int64 original_proxy_enabled[] = {kOriginalLength}; + int64 received_proxy_enabled[] = {kReceivedLength}; + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original_proxy_enabled, 1, received_proxy_enabled, 1, + NULL, 0, NULL, 0); + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + original[0] += kOriginalLength; + received[0] += kReceivedLength; + original_proxy_enabled[0] += kOriginalLength; + received_proxy_enabled[0] += kReceivedLength; + int64 original_via_proxy[] = {kOriginalLength}; + int64 received_via_proxy[] = {kReceivedLength}; + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original_proxy_enabled, 1, received_proxy_enabled, 1, + original_via_proxy, 1, received_via_proxy, 1); + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, UNKNOWN_TYPE, FakeNow()); + original[0] += kOriginalLength; + received[0] += kReceivedLength; + original_proxy_enabled[0] += kOriginalLength; + received_proxy_enabled[0] += kReceivedLength; + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original_proxy_enabled, 1, received_proxy_enabled, 1, + original_via_proxy, 1, received_via_proxy, 1); + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, false, UNKNOWN_TYPE, FakeNow()); + original[0] += kOriginalLength; + received[0] += kReceivedLength; + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original_proxy_enabled, 1, received_proxy_enabled, 1, + original_via_proxy, 1, received_via_proxy, 1); +} + +TEST_F(DataReductionProxyCompressionStatsTest, RequestType) { + const int64 kContentLength = 200; + int64 received[] = {0}; + int64 https_received[] = {0}; + int64 total_received[] = {0}; + int64 proxy_enabled_received[] = {0}; + + RecordContentLengthPrefs( + kContentLength, kContentLength, true, HTTPS, FakeNow()); + total_received[0] += kContentLength; + proxy_enabled_received[0] += kContentLength; + https_received[0] += kContentLength; + VerifyDailyRequestTypeContentLengthPrefLists( + total_received, 1, total_received, 1, + proxy_enabled_received, 1, proxy_enabled_received, 1, + https_received, 1, + received, 0, // short bypass + received, 0, // long bypass + received, 0); // unknown + + // Data reduction proxy is not enabled. + RecordContentLengthPrefs( + kContentLength, kContentLength, false, HTTPS, FakeNow()); + total_received[0] += kContentLength; + VerifyDailyRequestTypeContentLengthPrefLists( + total_received, 1, total_received, 1, + proxy_enabled_received, 1, proxy_enabled_received, 1, + https_received, 1, + received, 0, // short bypass + received, 0, // long bypass + received, 0); // unknown + + RecordContentLengthPrefs( + kContentLength, kContentLength, true, HTTPS, FakeNow()); + total_received[0] += kContentLength; + proxy_enabled_received[0] += kContentLength; + https_received[0] += kContentLength; + VerifyDailyRequestTypeContentLengthPrefLists( + total_received, 1, total_received, 1, + proxy_enabled_received, 1, proxy_enabled_received, 1, + https_received, 1, + received, 0, // short bypass + received, 0, // long bypass + received, 0); // unknown + + RecordContentLengthPrefs( + kContentLength, kContentLength, true, SHORT_BYPASS, FakeNow()); + total_received[0] += kContentLength; + proxy_enabled_received[0] += kContentLength; + received[0] += kContentLength; + VerifyDailyRequestTypeContentLengthPrefLists( + total_received, 1, total_received, 1, + proxy_enabled_received, 1, proxy_enabled_received, 1, + https_received, 1, + received, 1, // short bypass + received, 0, // long bypass + received, 0); // unknown + + RecordContentLengthPrefs( + kContentLength, kContentLength, true, LONG_BYPASS, FakeNow()); + total_received[0] += kContentLength; + proxy_enabled_received[0] += kContentLength; + VerifyDailyRequestTypeContentLengthPrefLists( + total_received, 1, total_received, 1, // total + proxy_enabled_received, 1, proxy_enabled_received, 1, + https_received, 1, + received, 1, // short bypass + received, 1, // long bypass + received, 0); // unknown + + RecordContentLengthPrefs( + kContentLength, kContentLength, true, UNKNOWN_TYPE, FakeNow()); + total_received[0] += kContentLength; + proxy_enabled_received[0] += kContentLength; + VerifyDailyRequestTypeContentLengthPrefLists( + total_received, 1, total_received, 1, + proxy_enabled_received, 1, proxy_enabled_received, 1, + https_received, 1, + received, 1, // short bypass + received, 1, // long bypass + received, 1); // unknown +} + +TEST_F(DataReductionProxyCompressionStatsTest, ForwardOneDay) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + + // Forward one day. + SetFakeTimeDeltaInHours(24); + + // Proxy not enabled. Not via proxy. + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, false, UNKNOWN_TYPE, FakeNow()); + + int64 original[] = {kOriginalLength, kOriginalLength}; + int64 received[] = {kReceivedLength, kReceivedLength}; + int64 original_with_data_reduction_proxy_enabled[] = {kOriginalLength, 0}; + int64 received_with_data_reduction_proxy_enabled[] = {kReceivedLength, 0}; + int64 original_via_data_reduction_proxy[] = {kOriginalLength, 0}; + int64 received_via_data_reduction_proxy[] = {kReceivedLength, 0}; + VerifyDailyDataSavingContentLengthPrefLists( + original, 2, + received, 2, + original_with_data_reduction_proxy_enabled, 2, + received_with_data_reduction_proxy_enabled, 2, + original_via_data_reduction_proxy, 2, + received_via_data_reduction_proxy, 2); + + // Proxy enabled. Not via proxy. + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, UNKNOWN_TYPE, FakeNow()); + original[1] += kOriginalLength; + received[1] += kReceivedLength; + original_with_data_reduction_proxy_enabled[1] += kOriginalLength; + received_with_data_reduction_proxy_enabled[1] += kReceivedLength; + VerifyDailyDataSavingContentLengthPrefLists( + original, 2, + received, 2, + original_with_data_reduction_proxy_enabled, 2, + received_with_data_reduction_proxy_enabled, 2, + original_via_data_reduction_proxy, 2, + received_via_data_reduction_proxy, 2); + + // Proxy enabled and via proxy. + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + original[1] += kOriginalLength; + received[1] += kReceivedLength; + original_with_data_reduction_proxy_enabled[1] += kOriginalLength; + received_with_data_reduction_proxy_enabled[1] += kReceivedLength; + original_via_data_reduction_proxy[1] += kOriginalLength; + received_via_data_reduction_proxy[1] += kReceivedLength; + VerifyDailyDataSavingContentLengthPrefLists( + original, 2, + received, 2, + original_with_data_reduction_proxy_enabled, 2, + received_with_data_reduction_proxy_enabled, 2, + original_via_data_reduction_proxy, 2, + received_via_data_reduction_proxy, 2); +} + +TEST_F(DataReductionProxyCompressionStatsTest, PartialDayTimeChange) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + int64 original[] = {0, kOriginalLength}; + int64 received[] = {0, kReceivedLength}; + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + VerifyDailyDataSavingContentLengthPrefLists( + original, 2, received, 2, + original, 2, received, 2, + original, 2, received, 2); + + // Forward 10 hours, stay in the same day. + // See kLastUpdateTime: "Now" in test is 03:45am. + SetFakeTimeDeltaInHours(10); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + original[1] += kOriginalLength; + received[1] += kReceivedLength; + VerifyDailyDataSavingContentLengthPrefLists( + original, 2, received, 2, + original, 2, received, 2, + original, 2, received, 2); + + // Forward 11 more hours, comes to tomorrow. + AddFakeTimeDeltaInHours(11); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + int64 original2[] = {kOriginalLength * 2, kOriginalLength}; + int64 received2[] = {kReceivedLength * 2, kReceivedLength}; + VerifyDailyDataSavingContentLengthPrefLists( + original2, 2, received2, 2, + original2, 2, received2, 2, + original2, 2, received2, 2); +} + +TEST_F(DataReductionProxyCompressionStatsTest, ForwardMultipleDays) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + + // Forward three days. + SetFakeTimeDeltaInHours(3 * 24); + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + + int64 original[] = {kOriginalLength, 0, 0, kOriginalLength}; + int64 received[] = {kReceivedLength, 0, 0, kReceivedLength}; + VerifyDailyDataSavingContentLengthPrefLists( + original, 4, received, 4, + original, 4, received, 4, + original, 4, received, 4); + + // Forward four more days. + AddFakeTimeDeltaInHours(4 * 24); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + int64 original2[] = { + kOriginalLength, 0, 0, kOriginalLength, 0, 0, 0, kOriginalLength, + }; + int64 received2[] = { + kReceivedLength, 0, 0, kReceivedLength, 0, 0, 0, kReceivedLength, + }; + VerifyDailyDataSavingContentLengthPrefLists( + original2, 8, received2, 8, + original2, 8, received2, 8, + original2, 8, received2, 8); + + // Forward |kNumDaysInHistory| more days. + AddFakeTimeDeltaInHours(kNumDaysInHistory * 24); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + int64 original3[] = {kOriginalLength}; + int64 received3[] = {kReceivedLength}; + VerifyDailyDataSavingContentLengthPrefLists( + original3, 1, received3, 1, + original3, 1, received3, 1, + original3, 1, received3, 1); + + // Forward |kNumDaysInHistory| + 1 more days. + AddFakeTimeDeltaInHours((kNumDaysInHistory + 1)* 24); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + VerifyDailyDataSavingContentLengthPrefLists( + original3, 1, received3, 1, + original3, 1, received3, 1, + original3, 1, received3, 1); +} + +TEST_F(DataReductionProxyCompressionStatsTest, BackwardAndForwardOneDay) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + int64 original[] = {kOriginalLength}; + int64 received[] = {kReceivedLength}; + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + + // Backward one day. + SetFakeTimeDeltaInHours(-24); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + original[0] += kOriginalLength; + received[0] += kReceivedLength; + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original, 1, received, 1, + original, 1, received, 1); + + // Then, Forward one day + AddFakeTimeDeltaInHours(24); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + int64 original2[] = {kOriginalLength * 2, kOriginalLength}; + int64 received2[] = {kReceivedLength * 2, kReceivedLength}; + VerifyDailyDataSavingContentLengthPrefLists( + original2, 2, received2, 2, + original2, 2, received2, 2, + original2, 2, received2, 2); +} + +TEST_F(DataReductionProxyCompressionStatsTest, BackwardTwoDays) { + const int64 kOriginalLength = 200; + const int64 kReceivedLength = 100; + int64 original[] = {kOriginalLength}; + int64 received[] = {kReceivedLength}; + + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + // Backward two days. + SetFakeTimeDeltaInHours(-2 * 24); + RecordContentLengthPrefs( + kReceivedLength, kOriginalLength, true, VIA_DATA_REDUCTION_PROXY, + FakeNow()); + VerifyDailyDataSavingContentLengthPrefLists( + original, 1, received, 1, + original, 1, received, 1, + original, 1, received, 1); +} + } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc index bfbe85e..3c9ebef 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -64,10 +64,15 @@ configurator_.get(), event_store_.get())); } + // It is safe to use base::Unretained here, since it gets executed + // synchronously on the IO thread, and |this| outlives the caller (since the + // caller is owned by |this|. + bypass_stats_.reset(new DataReductionProxyBypassStats( + config_.get(), base::Bind(&DataReductionProxyIOData::SetUnreachable, + base::Unretained(this)))); request_options_.reset(new DataReductionProxyRequestOptions( client_, config_.get(), io_task_runner_)); request_options_->Init(); - if (use_config_client) { config_client_.reset(new DataReductionProxyConfigServiceClient( params.Pass(), GetBackoffPolicy(), request_options_.get(), @@ -127,20 +132,30 @@ new DataReductionProxyNetworkDelegate( wrapped_network_delegate.Pass(), config_.get(), request_options_.get(), configurator_.get())); - if (track_proxy_bypass_statistics && !bypass_stats_) { - bypass_stats_.reset(new DataReductionProxyBypassStats( - config_.get(), base::Bind(&DataReductionProxyIOData::SetUnreachable, - base::Unretained(this)), ui_task_runner_)); - network_delegate->InitIODataAndUMA(ui_task_runner_, this, &enabled_, - bypass_stats_.get()); - } + if (track_proxy_bypass_statistics) + network_delegate->InitIODataAndUMA(this, &enabled_, bypass_stats_.get()); return network_delegate.Pass(); } +void DataReductionProxyIOData::UpdateContentLengths( + int received_content_length, + int original_content_length, + bool data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type) { + DCHECK(io_task_runner_->BelongsToCurrentThread()); + ui_task_runner_->PostTask( + FROM_HERE, + base::Bind(&DataReductionProxyService::UpdateContentLengths, + service_, received_content_length, original_content_length, + data_reduction_proxy_enabled, request_type)); +} + void DataReductionProxyIOData::SetUnreachable(bool unreachable) { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - if (service_) - service_->settings()->SetUnreachable(unreachable); + DCHECK(io_task_runner_->BelongsToCurrentThread()); + ui_task_runner_->PostTask( + FROM_HERE, + base::Bind(&DataReductionProxyService::SetUnreachable, + service_, unreachable)); } } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h index 80eab78..e258ec4f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
@@ -10,6 +10,7 @@ #include "base/prefs/pref_member.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_debug_ui_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" @@ -20,12 +21,12 @@ namespace data_reduction_proxy { +class DataReductionProxyBypassStats; class DataReductionProxyConfig; class DataReductionProxyConfigServiceClient; class DataReductionProxyConfigurator; class DataReductionProxyEventStore; class DataReductionProxyService; -class DataReductionProxyBypassStats; // Contains and initializes all Data Reduction Proxy objects that operate on // the IO thread. @@ -67,9 +68,16 @@ scoped_ptr<net::NetworkDelegate> wrapped_network_delegate, bool track_proxy_bypass_statistics); + // Bridge methods to safely call to the UI thread objects. + void UpdateContentLengths(int received_content_length, + int original_content_length, + bool data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type); + // Returns true if the Data Reduction Proxy is enabled and false otherwise. bool IsEnabled() const; + // Various accessor methods. DataReductionProxyConfigurator* configurator() const { return configurator_.get(); } @@ -172,4 +180,3 @@ } // namespace data_reduction_proxy #endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_ -
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc index f0438b0..c9c92e1 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -114,7 +114,7 @@ base::Bind(&DataReductionProxyIODataTest::RequestCallback, base::Unretained(this)), nullptr); EXPECT_EQ(1, wrapped_network_delegate->created_requests()); - EXPECT_EQ(nullptr, io_data->bypass_stats()); + EXPECT_NE(nullptr, io_data->bypass_stats()); // Creating a second delegate with bypass statistics tracking should result // in usage stats being created.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc index 0408a7bd..39efaa9 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc
@@ -4,296 +4,19 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" -#include "base/metrics/histogram.h" -#include "base/prefs/pref_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" +#include "base/basictypes.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" -#include "net/base/host_port_pair.h" #include "net/base/load_flags.h" -#include "net/http/http_response_headers.h" +#include "net/http/http_response_info.h" #include "net/proxy/proxy_config.h" -#include "net/proxy/proxy_retry_info.h" #include "net/proxy/proxy_server.h" -#include "net/proxy/proxy_service.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "url/url_constants.h" namespace data_reduction_proxy { -namespace { - -// A bypass delay more than this is treated as a long delay. -const int kLongBypassDelayInSeconds = 30 * 60; - -// Increments an int64, stored as a string, in a ListPref at the specified -// index. The value must already exist and be a string representation of a -// number. -void AddInt64ToListPref(size_t index, - int64 length, - base::ListValue* list_update) { - int64 value = 0; - std::string old_string_value; - bool rv = list_update->GetString(index, &old_string_value); - DCHECK(rv); - if (rv) { - rv = base::StringToInt64(old_string_value, &value); - DCHECK(rv); - } - value += length; - list_update->Set(index, new base::StringValue(base::Int64ToString(value))); -} - -int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) { - std::string string_value; - if (!list_update.GetString(index, &string_value)) { - NOTREACHED(); - return 0; - } - - int64 value = 0; - bool rv = base::StringToInt64(string_value, &value); - DCHECK(rv); - return value; -} - -// Report UMA metrics for daily data reductions. -void RecordDailyContentLengthHistograms( - int64 original_length, - int64 received_length, - int64 original_length_with_data_reduction_enabled, - int64 received_length_with_data_reduction_enabled, - int64 original_length_via_data_reduction_proxy, - int64 received_length_via_data_reduction_proxy, - int64 https_length_with_data_reduction_enabled, - int64 short_bypass_length_with_data_reduction_enabled, - int64 long_bypass_length_with_data_reduction_enabled, - int64 unknown_length_with_data_reduction_enabled) { - // Report daily UMA only for days having received content. - if (original_length <= 0 || received_length <= 0) - return; - - // Record metrics in KB. - UMA_HISTOGRAM_COUNTS( - "Net.DailyOriginalContentLength", original_length >> 10); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength", received_length >> 10); - int percent = 0; - // UMA percentage cannot be negative. - if (original_length > received_length) { - percent = (100 * (original_length - received_length)) / original_length; - } - UMA_HISTOGRAM_PERCENTAGE("Net.DailyContentSavingPercent", percent); - - if (original_length_with_data_reduction_enabled <= 0 || - received_length_with_data_reduction_enabled <= 0) { - return; - } - - UMA_HISTOGRAM_COUNTS( - "Net.DailyOriginalContentLength_DataReductionProxyEnabled", - original_length_with_data_reduction_enabled >> 10); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength_DataReductionProxyEnabled", - received_length_with_data_reduction_enabled >> 10); - - int percent_data_reduction_proxy_enabled = 0; - // UMA percentage cannot be negative. - if (original_length_with_data_reduction_enabled > - received_length_with_data_reduction_enabled) { - percent_data_reduction_proxy_enabled = - 100 * (original_length_with_data_reduction_enabled - - received_length_with_data_reduction_enabled) / - original_length_with_data_reduction_enabled; - } - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentSavingPercent_DataReductionProxyEnabled", - percent_data_reduction_proxy_enabled); - - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentPercent_DataReductionProxyEnabled", - (100 * received_length_with_data_reduction_enabled) / received_length); - - DCHECK_GE(https_length_with_data_reduction_enabled, 0); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength_DataReductionProxyEnabled_Https", - https_length_with_data_reduction_enabled >> 10); - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentPercent_DataReductionProxyEnabled_Https", - (100 * https_length_with_data_reduction_enabled) / received_length); - - DCHECK_GE(short_bypass_length_with_data_reduction_enabled, 0); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength_DataReductionProxyEnabled_ShortBypass", - short_bypass_length_with_data_reduction_enabled >> 10); - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentPercent_DataReductionProxyEnabled_ShortBypass", - ((100 * short_bypass_length_with_data_reduction_enabled) / - received_length)); - - DCHECK_GE(long_bypass_length_with_data_reduction_enabled, 0); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength_DataReductionProxyEnabled_LongBypass", - long_bypass_length_with_data_reduction_enabled >> 10); - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentPercent_DataReductionProxyEnabled_LongBypass", - ((100 * long_bypass_length_with_data_reduction_enabled) / - received_length)); - - DCHECK_GE(unknown_length_with_data_reduction_enabled, 0); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength_DataReductionProxyEnabled_Unknown", - unknown_length_with_data_reduction_enabled >> 10); - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentPercent_DataReductionProxyEnabled_Unknown", - ((100 * unknown_length_with_data_reduction_enabled) / - received_length)); - - DCHECK_GE(original_length_via_data_reduction_proxy, 0); - UMA_HISTOGRAM_COUNTS( - "Net.DailyOriginalContentLength_ViaDataReductionProxy", - original_length_via_data_reduction_proxy >> 10); - DCHECK_GE(received_length_via_data_reduction_proxy, 0); - UMA_HISTOGRAM_COUNTS( - "Net.DailyContentLength_ViaDataReductionProxy", - received_length_via_data_reduction_proxy >> 10); - int percent_via_data_reduction_proxy = 0; - if (original_length_via_data_reduction_proxy > - received_length_via_data_reduction_proxy) { - percent_via_data_reduction_proxy = - 100 * (original_length_via_data_reduction_proxy - - received_length_via_data_reduction_proxy) / - original_length_via_data_reduction_proxy; - } - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentSavingPercent_ViaDataReductionProxy", - percent_via_data_reduction_proxy); - UMA_HISTOGRAM_PERCENTAGE( - "Net.DailyContentPercent_ViaDataReductionProxy", - (100 * received_length_via_data_reduction_proxy) / received_length); -} - -// Ensure list has exactly |length| elements, either by truncating at the -// front, or appending "0"'s to the back. -void MaintainContentLengthPrefsWindow(base::ListValue* list, size_t length) { - // Remove data for old days from the front. - while (list->GetSize() > length) - list->Remove(0, NULL); - // Newly added lists are empty. Add entries to back to fill the window, - // each initialized to zero. - while (list->GetSize() < length) - list->AppendString(base::Int64ToString(0)); - DCHECK_EQ(length, list->GetSize()); -} - -// DailyContentLengthUpdate maintains a data saving pref. The pref is a list -// of |kNumDaysInHistory| elements of daily total content lengths for the past -// |kNumDaysInHistory| days. -class DailyContentLengthUpdate { - public: - DailyContentLengthUpdate(const char* pref, - DataReductionProxyCompressionStats* pref_service) - : update_(pref_service->GetList(pref)) {} - - void UpdateForDataChange(int days_since_last_update) { - // New empty lists may have been created. Maintain the invariant that - // there should be exactly |kNumDaysInHistory| days in the histories. - MaintainContentLengthPrefsWindow(update_, kNumDaysInHistory); - if (days_since_last_update) { - MaintainContentLengthPrefForDateChange(days_since_last_update); - } - } - - // Update the lengths for the current day. - void Add(int content_length) { - AddInt64ToListPref(kNumDaysInHistory - 1, content_length, update_); - } - - int64 GetListPrefValue(size_t index) { - return ListPrefInt64Value(*update_, index); - } - - private: - // Update the list for date change and ensure the list has exactly |length| - // elements. The last entry in the list will be for the current day after - // the update. - void MaintainContentLengthPrefForDateChange(int days_since_last_update) { - if (days_since_last_update == -1) { - // The system may go backwards in time by up to a day for legitimate - // reasons, such as with changes to the time zone. In such cases, we - // keep adding to the current day. - // Note: we accept the fact that some reported data is shifted to - // the adjacent day if users travel back and forth across time zones. - days_since_last_update = 0; - } else if (days_since_last_update < -1) { - // Erase all entries if the system went backwards in time by more than - // a day. - update_->Clear(); - - days_since_last_update = kNumDaysInHistory; - } - DCHECK_GE(days_since_last_update, 0); - - // Add entries for days since last update event. This will make the - // lists longer than kNumDaysInHistory. The additional items will be cut off - // from the head of the lists by |MaintainContentLengthPrefsWindow|, below. - for (int i = 0; - i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory); - ++i) { - update_->AppendString(base::Int64ToString(0)); - } - - // Entries for new days may have been appended. Maintain the invariant that - // there should be exactly |kNumDaysInHistory| days in the histories. - MaintainContentLengthPrefsWindow(update_, kNumDaysInHistory); - } - - base::ListValue* update_; -}; - -// DailyDataSavingUpdate maintains a pair of data saving prefs, original_update_ -// and received_update_. pref_original is a list of |kNumDaysInHistory| elements -// of daily total original content lengths for the past |kNumDaysInHistory| -// days. pref_received is the corresponding list of the daily total received -// content lengths. -class DailyDataSavingUpdate { - public: - DailyDataSavingUpdate(const char* pref_original, - const char* pref_received, - DataReductionProxyCompressionStats* compression_stats) - : original_(pref_original, compression_stats), - received_(pref_received, compression_stats) {} - - void UpdateForDataChange(int days_since_last_update) { - original_.UpdateForDataChange(days_since_last_update); - received_.UpdateForDataChange(days_since_last_update); - } - - // Update the lengths for the current day. - void Add(int original_content_length, int received_content_length) { - original_.Add(original_content_length); - received_.Add(received_content_length); - } - - int64 GetOriginalListPrefValue(size_t index) { - return original_.GetListPrefValue(index); - } - int64 GetReceivedListPrefValue(size_t index) { - return received_.GetListPrefValue(index); - } - - private: - DailyContentLengthUpdate original_; - DailyContentLengthUpdate received_; -}; - -} // namespace - DataReductionProxyRequestType GetDataReductionProxyRequestType( const net::URLRequest& request, const net::ProxyConfig& data_reduction_proxy_config, @@ -350,140 +73,4 @@ return original_content_length; } -void UpdateContentLengthPrefsForDataReductionProxy( - int received_content_length, - int original_content_length, - bool with_data_reduction_proxy_enabled, - DataReductionProxyRequestType request_type, - base::Time now, - DataReductionProxyCompressionStats* compression_stats) { - // TODO(bengr): Remove this check once the underlying cause of - // http://crbug.com/287821 is fixed. For now, only continue if the current - // year is reported as being between 1972 and 2970. - base::TimeDelta time_since_unix_epoch = now - base::Time::UnixEpoch(); - const int kMinDaysSinceUnixEpoch = 365 * 2; // 2 years. - const int kMaxDaysSinceUnixEpoch = 365 * 1000; // 1000 years. - if (time_since_unix_epoch.InDays() < kMinDaysSinceUnixEpoch || - time_since_unix_epoch.InDays() > kMaxDaysSinceUnixEpoch) { - return; - } - - // Determine how many days it has been since the last update. - int64 then_internal = compression_stats->GetInt64( - data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate); - - // Local midnight could have been shifted due to time zone change. - // If time is null then don't care if midnight will be wrong shifted due to - // time zone change because it's still too much time ago. - base::Time then_midnight = base::Time::FromInternalValue(then_internal); - if (!then_midnight.is_null()) { - then_midnight = then_midnight.LocalMidnight(); - } - base::Time midnight = now.LocalMidnight(); - - int days_since_last_update = (midnight - then_midnight).InDays(); - - // Each day, we calculate the total number of bytes received and the total - // size of all corresponding resources before any data-reducing recompression - // is applied. These values are used to compute the data savings realized - // by applying our compression techniques. Totals for the last - // |kNumDaysInHistory| days are maintained. - DailyDataSavingUpdate total( - data_reduction_proxy::prefs::kDailyHttpOriginalContentLength, - data_reduction_proxy::prefs::kDailyHttpReceivedContentLength, - compression_stats); - total.UpdateForDataChange(days_since_last_update); - - DailyDataSavingUpdate proxy_enabled( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthWithDataReductionProxyEnabled, - data_reduction_proxy::prefs:: - kDailyContentLengthWithDataReductionProxyEnabled, - compression_stats); - proxy_enabled.UpdateForDataChange(days_since_last_update); - - DailyDataSavingUpdate via_proxy( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthViaDataReductionProxy, - data_reduction_proxy::prefs:: - kDailyContentLengthViaDataReductionProxy, - compression_stats); - via_proxy.UpdateForDataChange(days_since_last_update); - - DailyContentLengthUpdate https( - data_reduction_proxy::prefs:: - kDailyContentLengthHttpsWithDataReductionProxyEnabled, - compression_stats); - https.UpdateForDataChange(days_since_last_update); - - DailyContentLengthUpdate short_bypass( - data_reduction_proxy::prefs:: - kDailyContentLengthShortBypassWithDataReductionProxyEnabled, - compression_stats); - short_bypass.UpdateForDataChange(days_since_last_update); - - DailyContentLengthUpdate long_bypass( - data_reduction_proxy::prefs:: - kDailyContentLengthLongBypassWithDataReductionProxyEnabled, - compression_stats); - long_bypass.UpdateForDataChange(days_since_last_update); - - DailyContentLengthUpdate unknown( - data_reduction_proxy::prefs:: - kDailyContentLengthUnknownWithDataReductionProxyEnabled, - compression_stats); - unknown.UpdateForDataChange(days_since_last_update); - - total.Add(original_content_length, received_content_length); - if (with_data_reduction_proxy_enabled) { - proxy_enabled.Add(original_content_length, received_content_length); - // Ignore data source cases, if exist, when - // "with_data_reduction_proxy_enabled == false" - switch (request_type) { - case VIA_DATA_REDUCTION_PROXY: - via_proxy.Add(original_content_length, received_content_length); - break; - case HTTPS: - https.Add(received_content_length); - break; - case SHORT_BYPASS: - short_bypass.Add(received_content_length); - break; - case LONG_BYPASS: - long_bypass.Add(received_content_length); - break; - case UNKNOWN_TYPE: - unknown.Add(received_content_length); - break; - } - } - - if (days_since_last_update) { - // Record the last update time in microseconds in UTC. - compression_stats->SetInt64( - data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate, - midnight.ToInternalValue()); - - // A new day. Report the previous day's data if exists. We'll lose usage - // data if the last time Chrome was run was more than a day ago. - // Here, we prefer collecting less data but the collected data is - // associated with an accurate date. - if (days_since_last_update == 1) { - // The previous day's data point is the second one from the tail. - // Therefore (kNumDaysInHistory - 2) below. - RecordDailyContentLengthHistograms( - total.GetOriginalListPrefValue(kNumDaysInHistory - 2), - total.GetReceivedListPrefValue(kNumDaysInHistory - 2), - proxy_enabled.GetOriginalListPrefValue(kNumDaysInHistory - 2), - proxy_enabled.GetReceivedListPrefValue(kNumDaysInHistory - 2), - via_proxy.GetOriginalListPrefValue(kNumDaysInHistory - 2), - via_proxy.GetReceivedListPrefValue(kNumDaysInHistory - 2), - https.GetListPrefValue(kNumDaysInHistory - 2), - short_bypass.GetListPrefValue(kNumDaysInHistory - 2), - long_bypass.GetListPrefValue(kNumDaysInHistory - 2), - unknown.GetListPrefValue(kNumDaysInHistory - 2)); - } - } -} - } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h index 22d47ed..85dd909 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h
@@ -5,7 +5,9 @@ #ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_METRICS_H_ #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_METRICS_H_ -#include "base/time/time.h" +#include <vector> + +#include "base/basictypes.h" namespace net { class ProxyConfig; @@ -16,8 +18,22 @@ namespace data_reduction_proxy { +typedef std::vector<long long> ContentLengthList; + class DataReductionProxyConfig; -class DataReductionProxyCompressionStats; + +// A bypass delay more than this is treated as a long delay. +const int kLongBypassDelayInSeconds = 30 * 60; + +// The number of days of bandwidth usage statistics that are tracked. +const unsigned int kNumDaysInHistory = 60; + +// The number of days of bandwidth usage statistics that are presented. +const unsigned int kNumDaysInHistorySummary = 30; + +static_assert(kNumDaysInHistorySummary <= kNumDaysInHistory, + "kNumDaysInHistorySummary should be no larger than " + "kNumDaysInHistory"); enum DataReductionProxyRequestType { VIA_DATA_REDUCTION_PROXY, // A request served by the data reduction proxy. @@ -45,16 +61,6 @@ int64 original_content_length, int64 received_content_length); -// This is only exposed for testing. It is normally called by -// UpdateContentLengthPrefs. -void UpdateContentLengthPrefsForDataReductionProxy( - int received_content_length, - int original_content_length, - bool with_data_reduction_proxy_enabled, - DataReductionProxyRequestType request_type, - base::Time now, - DataReductionProxyCompressionStats* compression_stats); - } // namespace data_reduction_proxy #endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_METRICS_H_
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc index 6fe2b60..be48a2a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
@@ -6,19 +6,11 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/prefs/pref_registry_simple.h" -#include "base/prefs/pref_service.h" -#include "base/prefs/testing_pref_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/test/test_simple_task_runner.h" #include "base/time/time.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "net/base/load_flags.h" #include "net/log/net_log.h" #include "net/proxy/proxy_server.h" @@ -30,648 +22,10 @@ using net::MockRead; -namespace { - -int64 GetListPrefInt64Value( - const base::ListValue& list_update, size_t index) { - std::string string_value; - EXPECT_TRUE(list_update.GetString(index, &string_value)); - - int64 value = 0; - EXPECT_TRUE(base::StringToInt64(string_value, &value)); - return value; -} - -} // namespace - namespace data_reduction_proxy { -// Test UpdateContentLengthPrefs. -class ChromeNetworkDataSavingMetricsTest : public testing::Test { - protected: - ChromeNetworkDataSavingMetricsTest() {} - - void SetUp() override { - compression_stats_.reset(new DataReductionProxyCompressionStats( - &pref_service_, - scoped_refptr<base::TestSimpleTaskRunner>( - new base::TestSimpleTaskRunner()), - base::TimeDelta())); - PrefRegistrySimple* registry = pref_service_.registry(); - registry->RegisterInt64Pref( - data_reduction_proxy::prefs::kHttpReceivedContentLength, 0); - registry->RegisterInt64Pref( - data_reduction_proxy::prefs::kHttpOriginalContentLength, 0); - - registry->RegisterListPref(data_reduction_proxy::prefs:: - kDailyHttpOriginalContentLength); - registry->RegisterListPref(data_reduction_proxy::prefs:: - kDailyHttpReceivedContentLength); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthWithDataReductionProxyEnabled); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyContentLengthWithDataReductionProxyEnabled); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyContentLengthHttpsWithDataReductionProxyEnabled); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyContentLengthShortBypassWithDataReductionProxyEnabled); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyContentLengthLongBypassWithDataReductionProxyEnabled); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyContentLengthUnknownWithDataReductionProxyEnabled); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthViaDataReductionProxy); - registry->RegisterListPref( - data_reduction_proxy::prefs:: - kDailyContentLengthViaDataReductionProxy); - registry->RegisterInt64Pref( - data_reduction_proxy::prefs:: - kDailyHttpContentLengthLastUpdateDate, 0L); - registry->RegisterBooleanPref( - data_reduction_proxy::prefs::kDataReductionProxyEnabled, false); - } - - TestingPrefServiceSimple pref_service_; - scoped_ptr<DataReductionProxyCompressionStats> compression_stats_; -}; - -// The initial last update time used in test. There is no leap second a few -// days around this time used in the test. -// Note: No time zone is specified. Local time will be assumed by -// base::Time::FromString below. -const char kLastUpdateTime[] = "Wed, 18 Sep 2013 03:45:26"; - -class ChromeNetworkDailyDataSavingMetricsTest - : public ChromeNetworkDataSavingMetricsTest { - protected: - ChromeNetworkDailyDataSavingMetricsTest() { - base::Time::FromString(kLastUpdateTime, &now_); - } - - void SetUp() override { - ChromeNetworkDataSavingMetricsTest::SetUp(); - - // Only create two lists in Setup to test that adding new lists is fine. - CreatePrefList( - data_reduction_proxy::prefs::kDailyHttpOriginalContentLength); - CreatePrefList( - data_reduction_proxy::prefs::kDailyHttpReceivedContentLength); - } - - base::Time FakeNow() const { - return now_ + now_delta_; - } - - void SetFakeTimeDeltaInHours(int hours) { - now_delta_ = base::TimeDelta::FromHours(hours); - } - - void AddFakeTimeDeltaInHours(int hours) { - now_delta_ += base::TimeDelta::FromHours(hours); - } - - // Create daily pref list of |kNumDaysInHistory| zero values. - void CreatePrefList(const char* pref) { - base::ListValue* update = compression_stats_->GetList(pref); - update->Clear(); - for (size_t i = 0; i < kNumDaysInHistory; ++i) { - update->Insert(0, new base::StringValue(base::Int64ToString(0))); - } - } - - // Verify the pref list values are equal to the given values. - // If the count of values is less than kNumDaysInHistory, zeros are assumed - // at the beginning. - void VerifyPrefList(const char* pref, const int64* values, size_t count) { - ASSERT_GE(kNumDaysInHistory, count); - base::ListValue* update = compression_stats_->GetList(pref); - ASSERT_EQ(kNumDaysInHistory, update->GetSize()) << "Pref: " << pref; - - for (size_t i = 0; i < count; ++i) { - EXPECT_EQ( - values[i], - GetListPrefInt64Value(*update, kNumDaysInHistory - count + i)) - << "index=" << (kNumDaysInHistory - count + i); - } - for (size_t i = 0; i < kNumDaysInHistory - count; ++i) { - EXPECT_EQ(0, GetListPrefInt64Value(*update, i)) << "index=" << i; - } - } - - // Verify all daily data saving pref list values. - void VerifyDailyDataSavingContentLengthPrefLists( - const int64* original_values, size_t original_count, - const int64* received_values, size_t received_count, - const int64* original_with_data_reduction_proxy_enabled_values, - size_t original_with_data_reduction_proxy_enabled_count, - const int64* received_with_data_reduction_proxy_enabled_values, - size_t received_with_data_reduction_proxy_count, - const int64* original_via_data_reduction_proxy_values, - size_t original_via_data_reduction_proxy_count, - const int64* received_via_data_reduction_proxy_values, - size_t received_via_data_reduction_proxy_count) { - VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength, - original_values, original_count); - VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength, - received_values, received_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthWithDataReductionProxyEnabled, - original_with_data_reduction_proxy_enabled_values, - original_with_data_reduction_proxy_enabled_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthWithDataReductionProxyEnabled, - received_with_data_reduction_proxy_enabled_values, - received_with_data_reduction_proxy_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthViaDataReductionProxy, - original_via_data_reduction_proxy_values, - original_via_data_reduction_proxy_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthViaDataReductionProxy, - received_via_data_reduction_proxy_values, - received_via_data_reduction_proxy_count); - } - - // Verify daily data saving pref for request types. - void VerifyDailyRequestTypeContentLengthPrefLists( - const int64* original_values, size_t original_count, - const int64* received_values, size_t received_count, - const int64* original_with_data_reduction_proxy_enabled_values, - size_t original_with_data_reduction_proxy_enabled_count, - const int64* received_with_data_reduction_proxy_enabled_values, - size_t received_with_data_reduction_proxy_count, - const int64* https_with_data_reduction_proxy_enabled_values, - size_t https_with_data_reduction_proxy_enabled_count, - const int64* short_bypass_with_data_reduction_proxy_enabled_values, - size_t short_bypass_with_data_reduction_proxy_enabled_count, - const int64* long_bypass_with_data_reduction_proxy_enabled_values, - size_t long_bypass_with_data_reduction_proxy_enabled_count, - const int64* unknown_with_data_reduction_proxy_enabled_values, - size_t unknown_with_data_reduction_proxy_enabled_count) { - VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpOriginalContentLength, - original_values, original_count); - VerifyPrefList(data_reduction_proxy::prefs::kDailyHttpReceivedContentLength, - received_values, received_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyOriginalContentLengthWithDataReductionProxyEnabled, - original_with_data_reduction_proxy_enabled_values, - original_with_data_reduction_proxy_enabled_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthWithDataReductionProxyEnabled, - received_with_data_reduction_proxy_enabled_values, - received_with_data_reduction_proxy_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthHttpsWithDataReductionProxyEnabled, - https_with_data_reduction_proxy_enabled_values, - https_with_data_reduction_proxy_enabled_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthShortBypassWithDataReductionProxyEnabled, - short_bypass_with_data_reduction_proxy_enabled_values, - short_bypass_with_data_reduction_proxy_enabled_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthLongBypassWithDataReductionProxyEnabled, - long_bypass_with_data_reduction_proxy_enabled_values, - long_bypass_with_data_reduction_proxy_enabled_count); - VerifyPrefList( - data_reduction_proxy::prefs:: - kDailyContentLengthUnknownWithDataReductionProxyEnabled, - unknown_with_data_reduction_proxy_enabled_values, - unknown_with_data_reduction_proxy_enabled_count); - } - - private: - base::Time now_; - base::TimeDelta now_delta_; -}; - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, OneResponse) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - int64 original[] = {kOriginalLength}; - int64 received[] = {kReceivedLength}; - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original, 1, received, 1, - original, 1, received, 1); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, MultipleResponses) { - const int64 kOriginalLength = 150; - const int64 kReceivedLength = 100; - int64 original[] = {kOriginalLength}; - int64 received[] = {kReceivedLength}; - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - false, UNKNOWN_TYPE, - FakeNow(), compression_stats_.get()); - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - NULL, 0, NULL, 0, NULL, 0, NULL, 0); - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, UNKNOWN_TYPE, - FakeNow(), compression_stats_.get()); - original[0] += kOriginalLength; - received[0] += kReceivedLength; - int64 original_proxy_enabled[] = {kOriginalLength}; - int64 received_proxy_enabled[] = {kReceivedLength}; - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original_proxy_enabled, 1, received_proxy_enabled, 1, - NULL, 0, NULL, 0); - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - original[0] += kOriginalLength; - received[0] += kReceivedLength; - original_proxy_enabled[0] += kOriginalLength; - received_proxy_enabled[0] += kReceivedLength; - int64 original_via_proxy[] = {kOriginalLength}; - int64 received_via_proxy[] = {kReceivedLength}; - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original_proxy_enabled, 1, received_proxy_enabled, 1, - original_via_proxy, 1, received_via_proxy, 1); - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, UNKNOWN_TYPE, FakeNow(), compression_stats_.get()); - original[0] += kOriginalLength; - received[0] += kReceivedLength; - original_proxy_enabled[0] += kOriginalLength; - received_proxy_enabled[0] += kReceivedLength; - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original_proxy_enabled, 1, received_proxy_enabled, 1, - original_via_proxy, 1, received_via_proxy, 1); - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - false, UNKNOWN_TYPE, FakeNow(), compression_stats_.get()); - original[0] += kOriginalLength; - received[0] += kReceivedLength; - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original_proxy_enabled, 1, received_proxy_enabled, 1, - original_via_proxy, 1, received_via_proxy, 1); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, RequestType) { - const int64 kContentLength = 200; - int64 received[] = {0}; - int64 https_received[] = {0}; - int64 total_received[] = {0}; - int64 proxy_enabled_received[] = {0}; - - UpdateContentLengthPrefsForDataReductionProxy( - kContentLength, kContentLength, - true, HTTPS, - FakeNow(), compression_stats_.get()); - total_received[0] += kContentLength; - proxy_enabled_received[0] += kContentLength; - https_received[0] += kContentLength; - VerifyDailyRequestTypeContentLengthPrefLists( - total_received, 1, total_received, 1, - proxy_enabled_received, 1, proxy_enabled_received, 1, - https_received, 1, - received, 0, // short bypass - received, 0, // long bypass - received, 0); // unknown - - // Data reduction proxy is not enabled. - UpdateContentLengthPrefsForDataReductionProxy( - kContentLength, kContentLength, - false, HTTPS, - FakeNow(), compression_stats_.get()); - total_received[0] += kContentLength; - VerifyDailyRequestTypeContentLengthPrefLists( - total_received, 1, total_received, 1, - proxy_enabled_received, 1, proxy_enabled_received, 1, - https_received, 1, - received, 0, // short bypass - received, 0, // long bypass - received, 0); // unknown - - UpdateContentLengthPrefsForDataReductionProxy( - kContentLength, kContentLength, - true, HTTPS, - FakeNow(), compression_stats_.get()); - total_received[0] += kContentLength; - proxy_enabled_received[0] += kContentLength; - https_received[0] += kContentLength; - VerifyDailyRequestTypeContentLengthPrefLists( - total_received, 1, total_received, 1, - proxy_enabled_received, 1, proxy_enabled_received, 1, - https_received, 1, - received, 0, // short bypass - received, 0, // long bypass - received, 0); // unknown - - UpdateContentLengthPrefsForDataReductionProxy( - kContentLength, kContentLength, - true, SHORT_BYPASS, - FakeNow(), compression_stats_.get()); - total_received[0] += kContentLength; - proxy_enabled_received[0] += kContentLength; - received[0] += kContentLength; - VerifyDailyRequestTypeContentLengthPrefLists( - total_received, 1, total_received, 1, - proxy_enabled_received, 1, proxy_enabled_received, 1, - https_received, 1, - received, 1, // short bypass - received, 0, // long bypass - received, 0); // unknown - - UpdateContentLengthPrefsForDataReductionProxy( - kContentLength, kContentLength, - true, LONG_BYPASS, - FakeNow(), compression_stats_.get()); - total_received[0] += kContentLength; - proxy_enabled_received[0] += kContentLength; - VerifyDailyRequestTypeContentLengthPrefLists( - total_received, 1, total_received, 1, // total - proxy_enabled_received, 1, proxy_enabled_received, 1, - https_received, 1, - received, 1, // short bypass - received, 1, // long bypass - received, 0); // unknown - - UpdateContentLengthPrefsForDataReductionProxy( - kContentLength, kContentLength, - true, UNKNOWN_TYPE, - FakeNow(), compression_stats_.get()); - total_received[0] += kContentLength; - proxy_enabled_received[0] += kContentLength; - VerifyDailyRequestTypeContentLengthPrefLists( - total_received, 1, total_received, 1, - proxy_enabled_received, 1, proxy_enabled_received, 1, - https_received, 1, - received, 1, // short bypass - received, 1, // long bypass - received, 1); // unknown -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, ForwardOneDay) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - - // Forward one day. - SetFakeTimeDeltaInHours(24); - - // Proxy not enabled. Not via proxy. - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - false, UNKNOWN_TYPE, FakeNow(), compression_stats_.get()); - - int64 original[] = {kOriginalLength, kOriginalLength}; - int64 received[] = {kReceivedLength, kReceivedLength}; - int64 original_with_data_reduction_proxy_enabled[] = {kOriginalLength, 0}; - int64 received_with_data_reduction_proxy_enabled[] = {kReceivedLength, 0}; - int64 original_via_data_reduction_proxy[] = {kOriginalLength, 0}; - int64 received_via_data_reduction_proxy[] = {kReceivedLength, 0}; - VerifyDailyDataSavingContentLengthPrefLists( - original, 2, - received, 2, - original_with_data_reduction_proxy_enabled, 2, - received_with_data_reduction_proxy_enabled, 2, - original_via_data_reduction_proxy, 2, - received_via_data_reduction_proxy, 2); - - // Proxy enabled. Not via proxy. - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, UNKNOWN_TYPE, FakeNow(), compression_stats_.get()); - original[1] += kOriginalLength; - received[1] += kReceivedLength; - original_with_data_reduction_proxy_enabled[1] += kOriginalLength; - received_with_data_reduction_proxy_enabled[1] += kReceivedLength; - VerifyDailyDataSavingContentLengthPrefLists( - original, 2, - received, 2, - original_with_data_reduction_proxy_enabled, 2, - received_with_data_reduction_proxy_enabled, 2, - original_via_data_reduction_proxy, 2, - received_via_data_reduction_proxy, 2); - - // Proxy enabled and via proxy. - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - original[1] += kOriginalLength; - received[1] += kReceivedLength; - original_with_data_reduction_proxy_enabled[1] += kOriginalLength; - received_with_data_reduction_proxy_enabled[1] += kReceivedLength; - original_via_data_reduction_proxy[1] += kOriginalLength; - received_via_data_reduction_proxy[1] += kReceivedLength; - VerifyDailyDataSavingContentLengthPrefLists( - original, 2, - received, 2, - original_with_data_reduction_proxy_enabled, 2, - received_with_data_reduction_proxy_enabled, 2, - original_via_data_reduction_proxy, 2, - received_via_data_reduction_proxy, 2); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, PartialDayTimeChange) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - int64 original[] = {0, kOriginalLength}; - int64 received[] = {0, kReceivedLength}; - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - VerifyDailyDataSavingContentLengthPrefLists( - original, 2, received, 2, - original, 2, received, 2, - original, 2, received, 2); - - // Forward 10 hours, stay in the same day. - // See kLastUpdateTime: "Now" in test is 03:45am. - SetFakeTimeDeltaInHours(10); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - original[1] += kOriginalLength; - received[1] += kReceivedLength; - VerifyDailyDataSavingContentLengthPrefLists( - original, 2, received, 2, - original, 2, received, 2, - original, 2, received, 2); - - // Forward 11 more hours, comes to tomorrow. - AddFakeTimeDeltaInHours(11); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - int64 original2[] = {kOriginalLength * 2, kOriginalLength}; - int64 received2[] = {kReceivedLength * 2, kReceivedLength}; - VerifyDailyDataSavingContentLengthPrefLists( - original2, 2, received2, 2, - original2, 2, received2, 2, - original2, 2, received2, 2); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, ForwardMultipleDays) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - - // Forward three days. - SetFakeTimeDeltaInHours(3 * 24); - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - - int64 original[] = {kOriginalLength, 0, 0, kOriginalLength}; - int64 received[] = {kReceivedLength, 0, 0, kReceivedLength}; - VerifyDailyDataSavingContentLengthPrefLists( - original, 4, received, 4, - original, 4, received, 4, - original, 4, received, 4); - - // Forward four more days. - AddFakeTimeDeltaInHours(4 * 24); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - int64 original2[] = { - kOriginalLength, 0, 0, kOriginalLength, 0, 0, 0, kOriginalLength, - }; - int64 received2[] = { - kReceivedLength, 0, 0, kReceivedLength, 0, 0, 0, kReceivedLength, - }; - VerifyDailyDataSavingContentLengthPrefLists( - original2, 8, received2, 8, - original2, 8, received2, 8, - original2, 8, received2, 8); - - // Forward |kNumDaysInHistory| more days. - AddFakeTimeDeltaInHours(kNumDaysInHistory * 24); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - int64 original3[] = {kOriginalLength}; - int64 received3[] = {kReceivedLength}; - VerifyDailyDataSavingContentLengthPrefLists( - original3, 1, received3, 1, - original3, 1, received3, 1, - original3, 1, received3, 1); - - // Forward |kNumDaysInHistory| + 1 more days. - AddFakeTimeDeltaInHours((kNumDaysInHistory + 1)* 24); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - VerifyDailyDataSavingContentLengthPrefLists( - original3, 1, received3, 1, - original3, 1, received3, 1, - original3, 1, received3, 1); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, BackwardAndForwardOneDay) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - int64 original[] = {kOriginalLength}; - int64 received[] = {kReceivedLength}; - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - - // Backward one day. - SetFakeTimeDeltaInHours(-24); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - original[0] += kOriginalLength; - received[0] += kReceivedLength; - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original, 1, received, 1, - original, 1, received, 1); - - // Then, Forward one day - AddFakeTimeDeltaInHours(24); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - int64 original2[] = {kOriginalLength * 2, kOriginalLength}; - int64 received2[] = {kReceivedLength * 2, kReceivedLength}; - VerifyDailyDataSavingContentLengthPrefLists( - original2, 2, received2, 2, - original2, 2, received2, 2, - original2, 2, received2, 2); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, BackwardTwoDays) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - int64 original[] = {kOriginalLength}; - int64 received[] = {kReceivedLength}; - - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - // Backward two days. - SetFakeTimeDeltaInHours(-2 * 24); - UpdateContentLengthPrefsForDataReductionProxy( - kReceivedLength, kOriginalLength, - true, VIA_DATA_REDUCTION_PROXY, - FakeNow(), compression_stats_.get()); - VerifyDailyDataSavingContentLengthPrefLists( - original, 1, received, 1, - original, 1, received, 1, - original, 1, received, 1); -} - -TEST_F(ChromeNetworkDailyDataSavingMetricsTest, - GetDataReductionProxyRequestType) { +TEST(ChromeNetworkDailyDataSavingMetricsTest, + GetDataReductionProxyRequestType) { scoped_ptr<DataReductionProxyTestContext> test_context = DataReductionProxyTestContext::Builder() .WithParamsFlags(DataReductionProxyParams::kAllowed)
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc index fbe71f6..c9b9cb1b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -8,16 +8,13 @@ #include "base/bind_helpers.h" #include "base/metrics/histogram.h" #include "base/prefs/pref_service.h" -#include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" @@ -82,7 +79,6 @@ DataReductionProxyRequestOptions* request_options, const DataReductionProxyConfigurator* configurator) : LayeredNetworkDelegate(network_delegate.Pass()), - ui_task_runner_(NULL), received_content_length_(0), original_content_length_(0), data_reduction_proxy_enabled_(NULL), @@ -98,13 +94,11 @@ } void DataReductionProxyNetworkDelegate::InitIODataAndUMA( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, DataReductionProxyIOData* io_data, BooleanPrefMember* data_reduction_proxy_enabled, DataReductionProxyBypassStats* bypass_stats) { DCHECK(data_reduction_proxy_enabled); DCHECK(bypass_stats); - ui_task_runner_ = ui_task_runner; data_reduction_proxy_io_data_ = io_data; data_reduction_proxy_enabled_ = data_reduction_proxy_enabled; data_reduction_proxy_bypass_stats_ = bypass_stats; @@ -218,51 +212,14 @@ DCHECK_GE(received_content_length, 0); DCHECK_GE(original_content_length, 0); if (data_reduction_proxy_enabled_) { - ui_task_runner_->PostTask( - FROM_HERE, - base::Bind(&DataReductionProxyNetworkDelegate::UpdateContentLengthPrefs, - base::Unretained(this), - received_content_length, - original_content_length, - data_reduction_proxy_enabled_->GetValue(), - request_type)); + data_reduction_proxy_io_data_->UpdateContentLengths( + received_content_length, original_content_length, + data_reduction_proxy_enabled_->GetValue(), request_type); } received_content_length_ += received_content_length; original_content_length_ += original_content_length; } -void DataReductionProxyNetworkDelegate::UpdateContentLengthPrefs( - int received_content_length, - int original_content_length, - bool data_reduction_proxy_enabled, - DataReductionProxyRequestType request_type) { - if (data_reduction_proxy_io_data_ && - data_reduction_proxy_io_data_->service()) { - DataReductionProxyCompressionStats* data_reduction_proxy_compression_stats = - data_reduction_proxy_io_data_->service()->compression_stats(); - int64 total_received = data_reduction_proxy_compression_stats->GetInt64( - data_reduction_proxy::prefs::kHttpReceivedContentLength); - int64 total_original = data_reduction_proxy_compression_stats->GetInt64( - data_reduction_proxy::prefs::kHttpOriginalContentLength); - total_received += received_content_length; - total_original += original_content_length; - data_reduction_proxy_compression_stats->SetInt64( - data_reduction_proxy::prefs::kHttpReceivedContentLength, - total_received); - data_reduction_proxy_compression_stats->SetInt64( - data_reduction_proxy::prefs::kHttpOriginalContentLength, - total_original); - - UpdateContentLengthPrefsForDataReductionProxy( - received_content_length, - original_content_length, - data_reduction_proxy_enabled, - request_type, - base::Time::Now(), - data_reduction_proxy_compression_stats); - } -} - void OnResolveProxyHandler(const GURL& url, int load_flags, const net::ProxyConfig& data_reduction_proxy_config,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h index 08457ba..8cb016eb 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -7,9 +7,7 @@ #include "base/basictypes.h" #include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" #include "base/values.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "net/base/layered_network_delegate.h" @@ -22,10 +20,6 @@ class GURL; class PrefService; -namespace base { -class SingleThreadTaskRunner; -} - namespace net { class HttpResponseHeaders; class HttpRequestHeaders; @@ -39,11 +33,11 @@ namespace data_reduction_proxy { +class DataReductionProxyBypassStats; class DataReductionProxyConfig; class DataReductionProxyConfigurator; class DataReductionProxyIOData; class DataReductionProxyRequestOptions; -class DataReductionProxyBypassStats; // DataReductionProxyNetworkDelegate is a LayeredNetworkDelegate that wraps a // NetworkDelegate and adds Data Reduction Proxy specific logic. @@ -69,7 +63,6 @@ // Initializes member variables to record data reduction proxy prefs and // report UMA. void InitIODataAndUMA( - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, DataReductionProxyIOData* io_data, BooleanPrefMember* data_reduction_proxy_enabled, DataReductionProxyBypassStats* bypass_stats); @@ -117,15 +110,6 @@ int64 original_content_length, DataReductionProxyRequestType request_type); - // Records daily data savings statistics to prefs and reports data savings - // UMA. - void UpdateContentLengthPrefs(int received_content_length, - int original_content_length, - bool data_reduction_proxy_enabled, - DataReductionProxyRequestType request_type); - - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; - // Total size of all content (excluding headers) that has been received // over the network. int64 received_content_length_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index dcf65cd..bf130c2 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -4,15 +4,10 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" -#include "base/bind.h" -#include "base/bind_helpers.h" #include "base/metrics/field_trial.h" -#include "base/prefs/pref_registry_simple.h" -#include "base/prefs/testing_pref_service.h" #include "base/strings/string_number_conversions.h" #include "base/test/histogram_tester.h" #include "base/time/time.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" @@ -143,18 +138,10 @@ return test_context_->io_data(); } - TestingPrefServiceSimple* pref_service() const { - return test_context_->pref_service(); - } - TestDataReductionProxyConfig* config() { return test_context_->config(); } - DataReductionProxyCompressionStats* compression_stats() const { - return test_context_->data_reduction_proxy_service()->compression_stats(); - } - scoped_ptr<DataReductionProxyNetworkDelegate> data_reduction_proxy_network_delegate_; @@ -411,43 +398,4 @@ EXPECT_FALSE(other_proxy_info.is_direct()); } -TEST_F(DataReductionProxyNetworkDelegateTest, TotalLengths) { - const int64 kOriginalLength = 200; - const int64 kReceivedLength = 100; - - data_reduction_proxy_network_delegate_->data_reduction_proxy_io_data_ = - io_data(); - - data_reduction_proxy_network_delegate_->UpdateContentLengthPrefs( - kReceivedLength, kOriginalLength, - pref_service()->GetBoolean( - data_reduction_proxy::prefs::kDataReductionProxyEnabled), - UNKNOWN_TYPE); - - EXPECT_EQ(kReceivedLength, - compression_stats()->GetInt64( - data_reduction_proxy::prefs::kHttpReceivedContentLength)); - EXPECT_FALSE(pref_service()->GetBoolean( - data_reduction_proxy::prefs::kDataReductionProxyEnabled)); - EXPECT_EQ(kOriginalLength, - compression_stats()->GetInt64( - data_reduction_proxy::prefs::kHttpOriginalContentLength)); - - // Record the same numbers again, and total lengths should be doubled. - data_reduction_proxy_network_delegate_->UpdateContentLengthPrefs( - kReceivedLength, kOriginalLength, - pref_service()->GetBoolean( - data_reduction_proxy::prefs::kDataReductionProxyEnabled), - UNKNOWN_TYPE); - - EXPECT_EQ(kReceivedLength * 2, - compression_stats()->GetInt64( - data_reduction_proxy::prefs::kHttpReceivedContentLength)); - EXPECT_FALSE(pref_service()->GetBoolean( - data_reduction_proxy::prefs::kDataReductionProxyEnabled)); - EXPECT_EQ(kOriginalLength * 2, - compression_stats()->GetInt64( - data_reduction_proxy::prefs::kHttpOriginalContentLength)); -} - } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc index b4ec8e3..326d92a5 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
@@ -6,6 +6,7 @@ #include "base/sequenced_task_runner.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_status.h" @@ -35,11 +36,30 @@ PrefService* prefs, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, const base::TimeDelta& commit_delay) { + DCHECK(CalledOnValidThread()); DCHECK(!compression_stats_); compression_stats_.reset(new DataReductionProxyCompressionStats( prefs, ui_task_runner, commit_delay)); } +void DataReductionProxyService::UpdateContentLengths( + int received_content_length, + int original_content_length, + bool data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type) { + DCHECK(CalledOnValidThread()); + if (compression_stats_) { + compression_stats_->UpdateContentLengths( + received_content_length, original_content_length, + data_reduction_proxy_enabled, request_type); + } +} + +void DataReductionProxyService::SetUnreachable(bool unreachable) { + DCHECK(CalledOnValidThread()); + settings_->SetUnreachable(unreachable); +} + base::WeakPtr<DataReductionProxyService> DataReductionProxyService::GetWeakPtr() { DCHECK(CalledOnValidThread());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h index 1760c10b..bf44a458 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
@@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/non_thread_safe.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "net/url_request/url_fetcher_delegate.h" class GURL; @@ -66,6 +67,16 @@ scoped_refptr<base::SequencedTaskRunner> ui_task_runner, const base::TimeDelta& commit_delay); + // Records daily data savings statistics in |compression_stats_|. + void UpdateContentLengths(int received_content_length, + int original_content_length, + bool data_reduction_proxy_enabled, + DataReductionProxyRequestType request_type); + + // Records whether the Data Reduction Proxy is unreachable or not. + void SetUnreachable(bool unreachable); + + // Accessor methods. DataReductionProxyCompressionStats* compression_stats() const { return compression_stats_.get(); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc index 838689e..c9b2555 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -9,13 +9,10 @@ #include "base/metrics/histogram.h" #include "base/prefs/pref_member.h" #include "base/prefs/pref_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/values.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" @@ -24,18 +21,6 @@ const char kUMAProxyStartupStateHistogram[] = "DataReductionProxy.StartupState"; -int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) { - int64 val = 0; - std::string pref_value; - bool rv = list_value.GetString(index, &pref_value); - DCHECK(rv); - if (rv) { - rv = base::StringToInt64(pref_value, &val); - DCHECK(rv); - } - return val; -} - bool IsEnabledOnCommandLine() { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); @@ -167,17 +152,8 @@ int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(data_reduction_proxy_service_->compression_stats()); - int64 last_update_internal = - data_reduction_proxy_service_->compression_stats()->GetInt64( - prefs::kDailyHttpContentLengthLastUpdateDate); - base::Time last_update = base::Time::FromInternalValue(last_update_internal); - return static_cast<int64>(last_update.ToJsTime()); -} - -DataReductionProxySettings::ContentLengthList -DataReductionProxySettings::GetDailyOriginalContentLengths() { - DCHECK(thread_checker_.CalledOnValidThread()); - return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength); + return + data_reduction_proxy_service_->compression_stats()->GetLastUpdateTime(); } void DataReductionProxySettings::SetUnreachable(bool unreachable) { @@ -189,12 +165,6 @@ return unreachable_; } -DataReductionProxySettings::ContentLengthList -DataReductionProxySettings::GetDailyReceivedContentLengths() { - DCHECK(thread_checker_.CalledOnValidThread()); - return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength); -} - PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() { DCHECK(thread_checker_.CalledOnValidThread()); return prefs_; @@ -237,18 +207,7 @@ void DataReductionProxySettings::ResetDataReductionStatistics() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(data_reduction_proxy_service_->compression_stats()); - base::ListValue* original_update = - data_reduction_proxy_service_->compression_stats()->GetList( - prefs::kDailyHttpOriginalContentLength); - base::ListValue* received_update = - data_reduction_proxy_service_->compression_stats()->GetList( - prefs::kDailyHttpReceivedContentLength); - original_update->Clear(); - received_update->Clear(); - for (size_t i = 0; i < kNumDaysInHistory; ++i) { - original_update->AppendString(base::Int64ToString(0)); - received_update->AppendString(base::Int64ToString(0)); - } + data_reduction_proxy_service_->compression_stats()->ResetStatistics(); } void DataReductionProxySettings::MaybeActivateDataReductionProxy( @@ -292,19 +251,12 @@ PROXY_STARTUP_STATE_COUNT); } -DataReductionProxySettings::ContentLengthList +ContentLengthList DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) { DCHECK(thread_checker_.CalledOnValidThread()); - DataReductionProxySettings::ContentLengthList content_lengths; DCHECK(data_reduction_proxy_service_->compression_stats()); - const base::ListValue* list_value = - data_reduction_proxy_service_->compression_stats()->GetList(pref_name); - if (list_value->GetSize() == kNumDaysInHistory) { - for (size_t i = 0; i < kNumDaysInHistory; ++i) { - content_lengths.push_back(GetInt64PrefValue(*list_value, i)); - } - } - return content_lengths; + return data_reduction_proxy_service_->compression_stats()-> + GetDailyContentLengths(pref_name); } void DataReductionProxySettings::GetContentLengths( @@ -313,37 +265,10 @@ int64* received_content_length, int64* last_update_time) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK_LE(days, kNumDaysInHistory); DCHECK(data_reduction_proxy_service_->compression_stats()); - const base::ListValue* original_list = - data_reduction_proxy_service_->compression_stats()->GetList( - prefs::kDailyHttpOriginalContentLength); - const base::ListValue* received_list = - data_reduction_proxy_service_->compression_stats()->GetList( - prefs::kDailyHttpReceivedContentLength); - - if (original_list->GetSize() != kNumDaysInHistory || - received_list->GetSize() != kNumDaysInHistory) { - *original_content_length = 0L; - *received_content_length = 0L; - *last_update_time = 0L; - return; - } - - int64 orig = 0L; - int64 recv = 0L; - // Include days from the end of the list going backwards. - for (size_t i = kNumDaysInHistory - days; - i < kNumDaysInHistory; ++i) { - orig += GetInt64PrefValue(*original_list, i); - recv += GetInt64PrefValue(*received_list, i); - } - *original_content_length = orig; - *received_content_length = recv; - *last_update_time = - data_reduction_proxy_service_->compression_stats()->GetInt64( - prefs::kDailyHttpContentLengthLastUpdateDate); + data_reduction_proxy_service_->compression_stats()->GetContentLengths( + days, original_content_length, received_content_length, last_update_time); } } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h index ca19611..4b87b3ca 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
@@ -15,6 +15,7 @@ #include "base/memory/scoped_ptr.h" #include "base/prefs/pref_member.h" #include "base/threading/thread_checker.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" #include "url/gurl.h" class PrefService; @@ -27,21 +28,11 @@ class DataReductionProxyService; class DataReductionProxyCompressionStats; -// The number of days of bandwidth usage statistics that are tracked. -const unsigned int kNumDaysInHistory = 60; - // The header used to request a data reduction proxy pass through. When a // request is sent to the data reduction proxy with this header, it will respond // with the original uncompressed response. extern const char kDataReductionPassThroughHeader[]; -// The number of days of bandwidth usage statistics that are presented. -const unsigned int kNumDaysInHistorySummary = 30; - -static_assert(kNumDaysInHistorySummary <= kNumDaysInHistory, - "kNumDaysInHistorySummary should be no larger than " - "kNumDaysInHistory"); - // Values of the UMA DataReductionProxy.StartupState histogram. // This enum must remain synchronized with DataReductionProxyStartupState // in metrics/histograms/histograms.xml. @@ -59,7 +50,6 @@ // associated factory class, and refactor the Java call sites accordingly. class DataReductionProxySettings { public: - typedef std::vector<long long> ContentLengthList; typedef base::Callback<bool(const std::string&, const std::string&)> SyntheticFieldTrialRegistrationCallback; @@ -112,11 +102,6 @@ // daily original and received content lengths. int64 GetDataReductionLastUpdateTime(); - // Returns a vector containing the total size of all HTTP content that was - // received over the last |kNumDaysInHistory| before any compression by the - // data reduction proxy. Each element in the vector contains one day of data. - ContentLengthList GetDailyOriginalContentLengths(); - // Returns aggregate received and original content lengths over the specified // number of days, as well as the time these stats were last updated. void GetContentLengths(unsigned int days, @@ -132,10 +117,6 @@ // some of them should have. bool IsDataReductionProxyUnreachable(); - // Returns an vector containing the aggregate received HTTP content in the - // last |kNumDaysInHistory| days. - ContentLengthList GetDailyReceivedContentLengths(); - ContentLengthList GetDailyContentLengths(const char* pref_name); // Configures data reduction proxy. |at_startup| is true when this method is
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc index 5fda5071..3ff88cdf 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc
@@ -75,9 +75,8 @@ received_update->Insert(0, new base::StringValue(base::Int64ToString(i))); } last_update_time_ = base::Time::Now().LocalMidnight(); - settings_->data_reduction_proxy_service()->compression_stats()->SetInt64( - prefs::kDailyHttpContentLengthLastUpdateDate, - last_update_time_.ToInternalValue()); + pref_service->SetInt64(prefs::kDailyHttpContentLengthLastUpdateDate, + last_update_time_.ToInternalValue()); } template <class C>
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc index 92bb8112..90b873bd 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
@@ -357,7 +357,7 @@ } TEST_F(DataReductionProxySettingsTest, TestGetDailyContentLengths) { - DataReductionProxySettings::ContentLengthList result = + ContentLengthList result = settings_->GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength); ASSERT_FALSE(result.empty());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc index abdf5cc..7333914 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -185,6 +185,9 @@ request_options_ = request_options.Pass(); configurator_ = configurator.Pass(); config_client_ = config_client.Pass(); + bypass_stats_.reset(new DataReductionProxyBypassStats( + config_.get(), base::Bind(&DataReductionProxyIOData::SetUnreachable, + base::Unretained(this)))); io_task_runner_ = task_runner; ui_task_runner_ = task_runner; }
diff --git a/components/dom_distiller/core/BUILD.gn b/components/dom_distiller/core/BUILD.gn index cbc4c56c..a05b1a7 100644 --- a/components/dom_distiller/core/BUILD.gn +++ b/components/dom_distiller/core/BUILD.gn
@@ -70,6 +70,7 @@ "//net", "//skia", "//sync", + "//sync/protocol", # TODO(brettw) bug 475091: this should be unnecessary. "//third_party/re2", "//ui/base", "//url",
diff --git a/components/dom_distiller/core/css/distilledpage.css b/components/dom_distiller/core/css/distilledpage.css index e563d19..13a3967a 100644 --- a/components/dom_distiller/core/css/distilledpage.css +++ b/components/dom_distiller/core/css/distilledpage.css
@@ -142,7 +142,7 @@ h4, h5, h6 { - line-height: 1.296rem; + line-height: 1.296; margin-bottom: 0.444rem; } @@ -155,20 +155,51 @@ } #content { - margin-top: 1.296rem; + margin: 0.2rem; } /* Main margins. */ body { max-width: 800px; - margin: 0px auto; + margin: 0px; } #mainContent { - margin: 1.296rem 1.296rem auto; + margin: auto 0px; } +#articleHeader { + background-color: rgb(73, 73, 73); + color: white; + min-height: 90px; + width: 100%; +} + +#titleCollapse { + display: block; + overflow: hidden; +} + +#titleCollapse .verticalCenterOuter { + min-height: 90px; +} + +#titleHolder { + padding: 10px 30px; +} + +.verticalCenterOuter { + display: table; + height: 100%; +} + +.verticalCenterInner { + display: table-cell; + vertical-align: middle; +} + + /* Link colors for light, dark and sepia themes */ a:link { @@ -199,7 +230,7 @@ h1 { font-size: 1.7rem; - line-height: 1.9rem; + line-height: 1.296; margin-bottom: 0.444rem; } @@ -267,7 +298,7 @@ } pre { - line-height: 1.296rem; + line-height: 1.296; overflow-x: scroll; padding: .5em; }
diff --git a/components/dom_distiller/core/html/dom_distiller_viewer.html b/components/dom_distiller/core/html/dom_distiller_viewer.html index 67285614..02704ea 100644 --- a/components/dom_distiller/core/html/dom_distiller_viewer.html +++ b/components/dom_distiller/core/html/dom_distiller_viewer.html
@@ -16,8 +16,14 @@ <div class="contentWrap"> <div id="mainContent"> <article> - <header> - <h1>$1</h1> + <header id="articleHeader"> + <div id="titleCollapse"> + <div class="verticalCenterOuter"> + <div class="verticalCenterInner"> + <h1 id="titleHolder">$1</h1> + </div> + </div> + </div> </header> <div id="content">$9</div> </article>
diff --git a/components/dom_distiller/core/javascript/dom_distiller_viewer.js b/components/dom_distiller/core/javascript/dom_distiller_viewer.js index b330fbbf..39d7f5c 100644 --- a/components/dom_distiller/core/javascript/dom_distiller_viewer.js +++ b/components/dom_distiller/core/javascript/dom_distiller_viewer.js
@@ -40,6 +40,21 @@ updateLoadingIndicator(isLastPage); } +// Sets the title. The title will be exposed with a simple animation. This +// should only be used when the title was not included in the initial html. +function setTitle(title) { + var holder = document.getElementById('titleHolder'); + var collapse = document.getElementById('titleCollapse'); + + collapse.style.height = "0px"; + + holder.textContent = title; + var newHeight = Math.max(90, holder.getBoundingClientRect().height); + + collapse.style.transition = "height 0.2s"; + collapse.style.height = newHeight + "px"; +} + // Maps JS Font Family to CSS class and then changes body class name. // CSS classes must agree with distilledpage.css. function useFontFamily(fontFamily) {
diff --git a/components/favicon.gypi b/components/favicon.gypi index f2c9cf54..d150316 100644 --- a/components/favicon.gypi +++ b/components/favicon.gypi
@@ -9,7 +9,9 @@ 'target_name': 'favicon_core', 'type': 'static_library', 'dependencies': [ + '../base/base.gyp:base', '../skia/skia.gyp:skia', + '../ui/base/ui_base.gyp:ui_base', '../ui/gfx/gfx.gyp:gfx', '../url/url.gyp:url_lib', 'bookmarks_browser', @@ -23,7 +25,10 @@ 'favicon/core/fallback_icon_service.cc', 'favicon/core/fallback_icon_service.h', 'favicon/core/favicon_client.h', + 'favicon/core/favicon_driver.cc', 'favicon/core/favicon_driver.h', + 'favicon/core/favicon_driver_impl.cc', + 'favicon/core/favicon_driver_impl.h', 'favicon/core/favicon_driver_observer.h', 'favicon/core/favicon_handler.cc', 'favicon/core/favicon_handler.h', @@ -45,13 +50,17 @@ 'target_name': 'favicon_content', 'type': 'static_library', 'dependencies': [ + '../base/base.gyp:base', '../content/content.gyp:content_browser', '../content/content.gyp:content_common', + '../ui/gfx/gfx.gyp:gfx', 'favicon_base', 'favicon_core', ], 'sources': [ # Note: sources list duplicated in GN build. + 'favicon/content/content_favicon_driver.cc', + 'favicon/content/content_favicon_driver.h', 'favicon/content/favicon_url_util.cc', 'favicon/content/favicon_url_util.h', ], @@ -67,13 +76,17 @@ 'target_name': 'favicon_ios', 'type': 'static_library', 'dependencies': [ + '../base/base.gyp:base', '../ios/web/ios_web.gyp:ios_web', + '../ui/gfx/gfx.gyp:gfx', 'favicon_base', 'favicon_core', ], 'sources': [ - 'favicon/ios/favicon_url_util.h', 'favicon/ios/favicon_url_util.cc', + 'favicon/ios/favicon_url_util.h', + 'favicon/ios/web_favicon_driver.cc', + 'favicon/ios/web_favicon_driver.h', ], 'include_dirs': [ '..',
diff --git a/components/favicon/DEPS b/components/favicon/DEPS index b6ea2b38..9c235365e 100644 --- a/components/favicon/DEPS +++ b/components/favicon/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+components/favicon_base", + "+ui/base", "+ui/gfx", ]
diff --git a/components/favicon/content/BUILD.gn b/components/favicon/content/BUILD.gn index 68501ea..1bea91e 100644 --- a/components/favicon/content/BUILD.gn +++ b/components/favicon/content/BUILD.gn
@@ -4,14 +4,18 @@ static_library("content") { sources = [ + "content_favicon_driver.cc", + "content_favicon_driver.h", "favicon_url_util.cc", "favicon_url_util.h", ] deps = [ + "//base", "//components/favicon/core", "//components/favicon_base", "//content/public/browser", "//content/public/common", + "//ui/gfx", ] }
diff --git a/components/favicon/content/content_favicon_driver.cc b/components/favicon/content/content_favicon_driver.cc new file mode 100644 index 0000000..c8efaad --- /dev/null +++ b/components/favicon/content/content_favicon_driver.cc
@@ -0,0 +1,182 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/favicon/content/content_favicon_driver.h" + +#include "base/bind.h" +#include "components/favicon/content/favicon_url_util.h" +#include "components/favicon/core/favicon_url.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/favicon_status.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/common/favicon_url.h" +#include "ui/gfx/image/image.h" + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(favicon::ContentFaviconDriver); + +namespace favicon { + +// static +void ContentFaviconDriver::CreateForWebContents( + content::WebContents* web_contents, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model) { + if (FromWebContents(web_contents)) + return; + + web_contents->SetUserData( + UserDataKey(), new ContentFaviconDriver(web_contents, favicon_service, + history_service, bookmark_model)); +} + +gfx::Image ContentFaviconDriver::GetFavicon() const { + // Like GetTitle(), we also want to use the favicon for the last committed + // entry rather than a pending navigation entry. + const content::NavigationController& controller = + web_contents()->GetController(); + content::NavigationEntry* entry = controller.GetTransientEntry(); + if (entry) + return entry->GetFavicon().image; + + entry = controller.GetLastCommittedEntry(); + if (entry) + return entry->GetFavicon().image; + return gfx::Image(); +} + +bool ContentFaviconDriver::FaviconIsValid() const { + const content::NavigationController& controller = + web_contents()->GetController(); + content::NavigationEntry* entry = controller.GetTransientEntry(); + if (entry) + return entry->GetFavicon().valid; + + entry = controller.GetLastCommittedEntry(); + if (entry) + return entry->GetFavicon().valid; + + return false; +} + +int ContentFaviconDriver::StartDownload(const GURL& url, int max_image_size) { + if (WasUnableToDownloadFavicon(url)) { + DVLOG(1) << "Skip Failed FavIcon: " << url; + return 0; + } + + bool bypass_cache = (bypass_cache_page_url_ == GetActiveURL()); + bypass_cache_page_url_ = GURL(); + + return web_contents()->DownloadImage( + url, true, max_image_size, bypass_cache, + base::Bind(&FaviconDriverImpl::DidDownloadFavicon, + base::Unretained(this))); +} + +bool ContentFaviconDriver::IsOffTheRecord() { + DCHECK(web_contents()); + return web_contents()->GetBrowserContext()->IsOffTheRecord(); +} + +GURL ContentFaviconDriver::GetActiveURL() { + content::NavigationEntry* entry = + web_contents()->GetController().GetActiveEntry(); + return entry ? entry->GetURL() : GURL(); +} + +base::string16 ContentFaviconDriver::GetActiveTitle() { + content::NavigationEntry* entry = + web_contents()->GetController().GetActiveEntry(); + return entry ? entry->GetTitle() : base::string16(); +} + +bool ContentFaviconDriver::GetActiveFaviconValidity() { + return GetFaviconStatus().valid; +} + +void ContentFaviconDriver::SetActiveFaviconValidity(bool valid) { + GetFaviconStatus().valid = valid; +} + +GURL ContentFaviconDriver::GetActiveFaviconURL() { + return GetFaviconStatus().url; +} + +void ContentFaviconDriver::SetActiveFaviconURL(const GURL& url) { + GetFaviconStatus().url = url; +} + +gfx::Image ContentFaviconDriver::GetActiveFaviconImage() { + return GetFaviconStatus().image; +} + +void ContentFaviconDriver::SetActiveFaviconImage(const gfx::Image& image) { + GetFaviconStatus().image = image; +} + +content::FaviconStatus& ContentFaviconDriver::GetFaviconStatus() { + DCHECK(web_contents()->GetController().GetActiveEntry()); + return web_contents()->GetController().GetActiveEntry()->GetFavicon(); +} + +ContentFaviconDriver::ContentFaviconDriver( + content::WebContents* web_contents, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model) + : content::WebContentsObserver(web_contents), + FaviconDriverImpl(favicon_service, history_service, bookmark_model) { +} + +ContentFaviconDriver::~ContentFaviconDriver() { +} + +void ContentFaviconDriver::NotifyFaviconUpdated(bool icon_url_changed) { + FaviconDriverImpl::NotifyFaviconUpdated(icon_url_changed); + web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB); +} + +void ContentFaviconDriver::DidUpdateFaviconURL( + const std::vector<content::FaviconURL>& candidates) { + DCHECK(!candidates.empty()); + favicon_urls_ = candidates; + OnUpdateFaviconURL(FaviconURLsFromContentFaviconURLs(candidates)); +} + +void ContentFaviconDriver::DidStartNavigationToPendingEntry( + const GURL& url, + content::NavigationController::ReloadType reload_type) { + if (reload_type == content::NavigationController::NO_RELOAD || + IsOffTheRecord()) + return; + + bypass_cache_page_url_ = url; + SetFaviconOutOfDateForPage( + url, reload_type == content::NavigationController::RELOAD_IGNORING_CACHE); +} + +void ContentFaviconDriver::DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + favicon_urls_.clear(); + + // Wait till the user navigates to a new URL to start checking the cache + // again. The cache may be ignored for non-reload navigations (e.g. + // history.replace() in-page navigation). This is allowed to increase the + // likelihood that "reloading a page ignoring the cache" redownloads the + // favicon. In particular, a page may do an in-page navigation before + // FaviconHandler has the time to determine that the favicon needs to be + // redownloaded. + GURL url = details.entry->GetURL(); + if (url != bypass_cache_page_url_) + bypass_cache_page_url_ = GURL(); + + // Get the favicon, either from history or request it from the net. + FetchFavicon(url); +} + +} // namespace favicon
diff --git a/components/favicon/content/content_favicon_driver.h b/components/favicon/content/content_favicon_driver.h new file mode 100644 index 0000000..18ef1bf --- /dev/null +++ b/components/favicon/content/content_favicon_driver.h
@@ -0,0 +1,88 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_FAVICON_CONTENT_CONTENT_FAVICON_DRIVER_H_ +#define COMPONENTS_FAVICON_CONTENT_CONTENT_FAVICON_DRIVER_H_ + +#include "components/favicon/core/favicon_driver_impl.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" +#include "url/gurl.h" + +namespace content { +struct FaviconStatus; +struct FaviconURL; +class WebContents; +} + +namespace favicon { + +// ContentFaviconDriver is an implementation of FaviconDriver that listens to +// WebContents events to start download of favicons and to get informed when the +// favicon download has completed. +class ContentFaviconDriver + : public content::WebContentsObserver, + public content::WebContentsUserData<ContentFaviconDriver>, + public FaviconDriverImpl { + public: + static void CreateForWebContents(content::WebContents* web_contents, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model); + + // Returns the current tab's favicon URLs. If this is empty, + // DidUpdateFaviconURL has not yet been called for the current navigation. + const std::vector<content::FaviconURL>& favicon_urls() const { + return favicon_urls_; + } + + // FaviconDriver implementation. + gfx::Image GetFavicon() const override; + bool FaviconIsValid() const override; + int StartDownload(const GURL& url, int max_bitmap_size) override; + bool IsOffTheRecord() override; + GURL GetActiveURL() override; + base::string16 GetActiveTitle() override; + bool GetActiveFaviconValidity() override; + void SetActiveFaviconValidity(bool valid) override; + GURL GetActiveFaviconURL() override; + void SetActiveFaviconURL(const GURL& url) override; + gfx::Image GetActiveFaviconImage() override; + void SetActiveFaviconImage(const gfx::Image& image) override; + + protected: + ContentFaviconDriver(content::WebContents* web_contents, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model); + ~ContentFaviconDriver() override; + + private: + friend class content::WebContentsUserData<ContentFaviconDriver>; + + // FaviconDriver implementation. + void NotifyFaviconUpdated(bool icon_url_changed) override; + + // content::WebContentsObserver implementation. + void DidUpdateFaviconURL( + const std::vector<content::FaviconURL>& candidates) override; + void DidStartNavigationToPendingEntry( + const GURL& url, + content::NavigationController::ReloadType reload_type) override; + void DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) override; + + // Returns the active navigation entry's favicon. + content::FaviconStatus& GetFaviconStatus(); + + GURL bypass_cache_page_url_; + std::vector<content::FaviconURL> favicon_urls_; + + DISALLOW_COPY_AND_ASSIGN(ContentFaviconDriver); +}; + +} // namespace favicon + +#endif // COMPONENTS_FAVICON_CONTENT_CONTENT_FAVICON_DRIVER_H_
diff --git a/components/favicon/core/BUILD.gn b/components/favicon/core/BUILD.gn index 4ac4750..7f9b762 100644 --- a/components/favicon/core/BUILD.gn +++ b/components/favicon/core/BUILD.gn
@@ -8,7 +8,10 @@ "fallback_icon_service.cc", "fallback_icon_service.h", "favicon_client.h", + "favicon_driver.cc", "favicon_driver.h", + "favicon_driver_impl.cc", + "favicon_driver_impl.h", "favicon_driver_observer.h", "favicon_handler.cc", "favicon_handler.h", @@ -19,11 +22,13 @@ ] deps = [ + "//base", "//components/bookmarks/browser", "//components/favicon_base", "//components/history/core/browser", "//components/keyed_service/core", "//skia", + "//ui/base", "//ui/gfx", "//url", ]
diff --git a/components/favicon/core/favicon_driver.cc b/components/favicon/core/favicon_driver.cc new file mode 100644 index 0000000..00632292 --- /dev/null +++ b/components/favicon/core/favicon_driver.cc
@@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/favicon/core/favicon_driver.h" + +#include "components/favicon/core/favicon_driver_observer.h" + +namespace favicon { + +void FaviconDriver::AddObserver(FaviconDriverObserver* observer) { + observer_list_.AddObserver(observer); +} + +void FaviconDriver::RemoveObserver(FaviconDriverObserver* observer) { + observer_list_.RemoveObserver(observer); +} + +FaviconDriver::FaviconDriver() { +} + +FaviconDriver::~FaviconDriver() { +} + +void FaviconDriver::NotifyFaviconAvailable(const gfx::Image& image) { + FOR_EACH_OBSERVER(FaviconDriverObserver, observer_list_, + OnFaviconAvailable(image)); +} + +void FaviconDriver::NotifyFaviconUpdated(bool icon_url_changed) { + FOR_EACH_OBSERVER(FaviconDriverObserver, observer_list_, + OnFaviconUpdated(this, icon_url_changed)); +} + +} // namespace favicon
diff --git a/components/favicon/core/favicon_driver.h b/components/favicon/core/favicon_driver.h index 4347ecb..a030845a 100644 --- a/components/favicon/core/favicon_driver.h +++ b/components/favicon/core/favicon_driver.h
@@ -6,6 +6,7 @@ #define COMPONENTS_FAVICON_CORE_FAVICON_DRIVER_H_ #include "base/macros.h" +#include "base/observer_list.h" #include "base/strings/string16.h" class GURL; @@ -16,11 +17,33 @@ namespace favicon { -// Interface that allows Favicon core code to interact with its driver (i.e., -// obtain information from it and give information to it). A concrete -// implementation must be provided by the driver. +class FaviconDriverObserver; + +// Interface that allows favicon core code to obtain information about the +// current page. This is partially implemented by FaviconDriverImpl, and +// concrete implementation should be based on that class instead of directly +// subclassing FaviconDriver. class FaviconDriver { public: + // Adds/Removes an observer. + void AddObserver(FaviconDriverObserver* observer); + void RemoveObserver(FaviconDriverObserver* observer); + + // Initiates loading the favicon for the specified url. + virtual void FetchFavicon(const GURL& url) = 0; + + // Saves the favicon for the current page. + virtual void SaveFavicon() = 0; + + // Returns the favicon for this tab, or IDR_DEFAULT_FAVICON if the tab does + // not have a favicon. The default implementation uses the current navigation + // entry. Returns an empty bitmap if there are no navigation entries, which + // should rarely happen. + virtual gfx::Image GetFavicon() const = 0; + + // Returns true if we have the favicon for the page. + virtual bool FaviconIsValid() const = 0; + // Starts the download for the given favicon. When finished, the driver // will call OnDidDownloadFavicon() with the results. // Returns the unique id of the download request. The id will be passed @@ -74,16 +97,26 @@ const GURL& icon_url, bool is_active_favicon) = 0; - // Sends notification that the current page favicon has changed. - // |icon_url_changed| is true if the URL of the favicon changed in addition to - // the favicon image. - virtual void NotifyFaviconUpdated(bool icon_url_changed) = 0; + // Returns whether the driver is waiting for a download to complete or for + // data from the FaviconService. Reserved for testing. + virtual bool HasPendingTasksForTest() = 0; protected: - FaviconDriver() {} - virtual ~FaviconDriver() {} + FaviconDriver(); + virtual ~FaviconDriver(); + + // Informs FaviconDriverObservers that favicon |image| has been retrieved from + // either website or cached storage. + void NotifyFaviconAvailable(const gfx::Image& image); + + // Informs FaviconDriverObservers that favicon has changed for the current + // page. |icon_url_changed| is true if the favicon URL has also changed since + // the last call. + virtual void NotifyFaviconUpdated(bool icon_url_changed); private: + ObserverList<FaviconDriverObserver> observer_list_; + DISALLOW_COPY_AND_ASSIGN(FaviconDriver); };
diff --git a/components/favicon/core/favicon_driver_impl.cc b/components/favicon/core/favicon_driver_impl.cc new file mode 100644 index 0000000..c95bf3aa --- /dev/null +++ b/components/favicon/core/favicon_driver_impl.cc
@@ -0,0 +1,178 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/favicon/core/favicon_driver_impl.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/metrics/field_trial.h" +#include "base/strings/string_util.h" +#include "components/bookmarks/browser/bookmark_model.h" +#include "components/favicon/core/favicon_driver_observer.h" +#include "components/favicon/core/favicon_handler.h" +#include "components/favicon/core/favicon_service.h" +#include "components/history/core/browser/history_service.h" +#include "ui/base/ui_base_switches.h" + +namespace favicon { +namespace { + +// Returns whether icon NTP is enabled by experiment. +// TODO(huangs): Remove all 3 copies of this routine once Icon NTP launches. +bool IsIconNTPEnabled() { + // Note: It's important to query the field trial state first, to ensure that + // UMA reports the correct group. + const std::string group_name = base::FieldTrialList::FindFullName("IconNTP"); + using base::CommandLine; + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableIconNtp)) + return false; + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp)) + return true; + + return StartsWithASCII(group_name, "Enabled", true); +} + +#if defined(OS_ANDROID) || defined(OS_IOS) +const bool kEnableTouchIcon = true; +#else +const bool kEnableTouchIcon = false; +#endif + +} // namespace + +FaviconDriverImpl::FaviconDriverImpl(FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model) + : favicon_service_(favicon_service), + history_service_(history_service), + bookmark_model_(bookmark_model) { + favicon_handler_.reset(new FaviconHandler( + favicon_service_, this, FaviconHandler::FAVICON, kEnableTouchIcon)); + if (kEnableTouchIcon) { + touch_icon_handler_.reset(new FaviconHandler(favicon_service_, this, + FaviconHandler::TOUCH, true)); + } + if (IsIconNTPEnabled()) { + large_icon_handler_.reset(new FaviconHandler(favicon_service_, this, + FaviconHandler::LARGE, true)); + } +} + +FaviconDriverImpl::~FaviconDriverImpl() { +} + +void FaviconDriverImpl::FetchFavicon(const GURL& url) { + favicon_handler_->FetchFavicon(url); + if (touch_icon_handler_.get()) + touch_icon_handler_->FetchFavicon(url); + if (large_icon_handler_.get()) + large_icon_handler_->FetchFavicon(url); +} + +void FaviconDriverImpl::SaveFavicon() { + GURL active_url = GetActiveURL(); + if (active_url.is_empty()) + return; + + // Make sure the page is in history, otherwise adding the favicon does + // nothing. + if (!history_service_) + return; + history_service_->AddPageNoVisitForBookmark(active_url, GetActiveTitle()); + + if (!favicon_service_) + return; + if (!GetActiveFaviconValidity()) + return; + GURL favicon_url = GetActiveFaviconURL(); + if (favicon_url.is_empty()) + return; + gfx::Image image = GetActiveFaviconImage(); + if (image.IsEmpty()) + return; + favicon_service_->SetFavicons(active_url, favicon_url, favicon_base::FAVICON, + image); +} + +void FaviconDriverImpl::DidDownloadFavicon( + int id, + int http_status_code, + const GURL& image_url, + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& original_bitmap_sizes) { + if (bitmaps.empty() && http_status_code == 404) { + DVLOG(1) << "Failed to Download Favicon:" << image_url; + if (favicon_service_) + favicon_service_->UnableToDownloadFavicon(image_url); + } + + favicon_handler_->OnDidDownloadFavicon(id, image_url, bitmaps, + original_bitmap_sizes); + if (touch_icon_handler_.get()) { + touch_icon_handler_->OnDidDownloadFavicon(id, image_url, bitmaps, + original_bitmap_sizes); + } + if (large_icon_handler_.get()) { + large_icon_handler_->OnDidDownloadFavicon(id, image_url, bitmaps, + original_bitmap_sizes); + } +} + +bool FaviconDriverImpl::IsBookmarked(const GURL& url) { + return bookmark_model_ && bookmark_model_->IsBookmarked(url); +} + +void FaviconDriverImpl::OnFaviconAvailable(const gfx::Image& image, + const GURL& icon_url, + bool is_active_favicon) { + if (is_active_favicon) { + bool icon_url_changed = GetActiveFaviconURL() != icon_url; + // No matter what happens, we need to mark the favicon as being set. + SetActiveFaviconValidity(true); + SetActiveFaviconURL(icon_url); + + if (image.IsEmpty()) + return; + + SetActiveFaviconImage(image); + NotifyFaviconUpdated(icon_url_changed); + } + if (!image.IsEmpty()) + NotifyFaviconAvailable(image); +} + +bool FaviconDriverImpl::HasPendingTasksForTest() { + if (favicon_handler_->HasPendingTasksForTest()) + return true; + if (touch_icon_handler_ && touch_icon_handler_->HasPendingTasksForTest()) + return true; + if (large_icon_handler_ && large_icon_handler_->HasPendingTasksForTest()) + return true; + return false; +} + +bool FaviconDriverImpl::WasUnableToDownloadFavicon(const GURL& url) { + return favicon_service_ && favicon_service_->WasUnableToDownloadFavicon(url); +} + +void FaviconDriverImpl::SetFaviconOutOfDateForPage(const GURL& url, + bool force_reload) { + if (favicon_service_) { + favicon_service_->SetFaviconOutOfDateForPage(url); + if (force_reload) + favicon_service_->ClearUnableToDownloadFavicons(); + } +} + +void FaviconDriverImpl::OnUpdateFaviconURL( + const std::vector<FaviconURL>& candidates) { + DCHECK(!candidates.empty()); + favicon_handler_->OnUpdateFaviconURL(candidates); + if (touch_icon_handler_.get()) + touch_icon_handler_->OnUpdateFaviconURL(candidates); + if (large_icon_handler_.get()) + large_icon_handler_->OnUpdateFaviconURL(candidates); +} + +} // namespace favicon
diff --git a/components/favicon/core/favicon_driver_impl.h b/components/favicon/core/favicon_driver_impl.h new file mode 100644 index 0000000..f4a93d6 --- /dev/null +++ b/components/favicon/core/favicon_driver_impl.h
@@ -0,0 +1,98 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_FAVICON_CORE_FAVICON_DRIVER_IMPL_H_ +#define COMPONENTS_FAVICON_CORE_FAVICON_DRIVER_IMPL_H_ + +#include <vector> + +#include "base/macros.h" +#include "components/favicon/core/favicon_driver.h" + +class GURL; +class SkBitmap; + +namespace bookmarks { +class BookmarkModel; +} + +namespace gfx { +class Image; +class Size; +} + +namespace history { +class HistoryService; +} + +namespace favicon { + +class FaviconDriverObserver; +class FaviconHandler; +class FaviconService; +struct FaviconURL; + +// FaviconDriverImpl is a partial implementation of FaviconDriver that allow +// sharing implementation between different embedder. +// +// FaviconDriverImpl works with FaviconHandlers to fetch the favicons. It +// fetches the given page's icons, requesting them from history backend. If the +// icon is not available or expired, the icon will be downloaded and saved in +// the history backend. +class FaviconDriverImpl : public FaviconDriver { + public: + // Favicon download callback. + // Public for testing. + void DidDownloadFavicon(int id, + int http_status_code, + const GURL& image_url, + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& original_bitmap_sizes); + + // FaviconDriver implementation. + void FetchFavicon(const GURL& url) override; + void SaveFavicon() override; + bool IsBookmarked(const GURL& url) override; + void OnFaviconAvailable(const gfx::Image& image, + const GURL& icon_url, + bool is_active_favicon) override; + bool HasPendingTasksForTest() override; + + protected: + FaviconDriverImpl(FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model); + ~FaviconDriverImpl() override; + + // Returns whether downloading favicon for |url| previously failed. + bool WasUnableToDownloadFavicon(const GURL& url); + + // Informs FaviconService that the favicon for |url| is out of date. If + // |force_reload| is true, then discard information about favicon download + // failures. + void SetFaviconOutOfDateForPage(const GURL& url, bool force_reload); + + // Broadcasts new favicon URL candidates to FaviconHandlers. + void OnUpdateFaviconURL(const std::vector<FaviconURL>& candidates); + + private: + // KeyedServices used by FaviconDriverImpl. They may be null during testing, + // but if they are defined, they must outlive the FaviconDriverImpl. + FaviconService* favicon_service_; + history::HistoryService* history_service_; + bookmarks::BookmarkModel* bookmark_model_; + + // FaviconHandlers used to download the different kind of favicons. Both + // |touch_icon_handler_| and |large_icon_handler_| may be null depending + // on the platform or variations. + scoped_ptr<FaviconHandler> favicon_handler_; + scoped_ptr<FaviconHandler> touch_icon_handler_; + scoped_ptr<FaviconHandler> large_icon_handler_; + + DISALLOW_COPY_AND_ASSIGN(FaviconDriverImpl); +}; + +} // namespace favicon + +#endif // COMPONENTS_FAVICON_CORE_FAVICON_DRIVER_IMPL_H_
diff --git a/components/favicon/core/favicon_handler.cc b/components/favicon/core/favicon_handler.cc index adc0a5c4..aff1626 100644 --- a/components/favicon/core/favicon_handler.cc +++ b/components/favicon/core/favicon_handler.cc
@@ -450,6 +450,11 @@ } } +bool FaviconHandler::HasPendingTasksForTest() { + return !download_requests_.empty() || + cancelable_task_tracker_.HasTrackedTasks(); +} + bool FaviconHandler::PageChangedSinceFaviconWasRequested() { if (UrlMatches(driver_->GetActiveURL(), url_) && url_.is_valid()) { return false;
diff --git a/components/favicon/core/favicon_handler.h b/components/favicon/core/favicon_handler.h index 960eba51..d8fee10 100644 --- a/components/favicon/core/favicon_handler.h +++ b/components/favicon/core/favicon_handler.h
@@ -19,7 +19,6 @@ #include "ui/gfx/image/image.h" #include "url/gurl.h" -class FaviconTabHelperTest; class SkBitmap; class TestFaviconHandler; @@ -118,6 +117,10 @@ return image_urls_; } + // Returns whether the handler is waiting for a download to complete or for + // data from the FaviconService. Reserved for testing. + bool HasPendingTasksForTest(); + protected: // These virtual methods make FaviconHandler testable and are overridden by // TestFaviconHandler. @@ -155,7 +158,6 @@ private: // For testing: - friend class ::FaviconTabHelperTest; friend class ::TestFaviconHandler; // Represents an in progress download of an image from the renderer.
diff --git a/components/favicon/core/favicon_service.cc b/components/favicon/core/favicon_service.cc index dd1ada4c..31c70412 100644 --- a/components/favicon/core/favicon_service.cc +++ b/components/favicon/core/favicon_service.cc
@@ -231,12 +231,6 @@ history_service_->SetFaviconsOutOfDateForPage(page_url); } -void FaviconService::CloneFavicon(const GURL& old_page_url, - const GURL& new_page_url) { - if (history_service_) - history_service_->CloneFavicons(old_page_url, new_page_url); -} - void FaviconService::SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) { if (history_service_)
diff --git a/components/favicon/core/favicon_service.h b/components/favicon/core/favicon_service.h index d122e906..e237967 100644 --- a/components/favicon/core/favicon_service.h +++ b/components/favicon/core/favicon_service.h
@@ -171,13 +171,6 @@ // Marks all types of favicon for the page as being out of date. void SetFaviconOutOfDateForPage(const GURL& page_url); - // Clones all icons from an existing page. This associates the icons from - // |old_page_url| with |new_page_url|, provided |new_page_url| has no - // recorded associations to any other icons. - // Needed if you want to declare favicons (tentatively) in advance, before a - // page is ever visited. - void CloneFavicon(const GURL& old_page_url, const GURL& new_page_url); - // Allows the importer to set many favicons for many pages at once. The pages // must exist, any favicon sets for unknown pages will be discarded. Existing // favicons will not be overwritten.
diff --git a/components/favicon/ios/web_favicon_driver.cc b/components/favicon/ios/web_favicon_driver.cc new file mode 100644 index 0000000..b4eaac7c --- /dev/null +++ b/components/favicon/ios/web_favicon_driver.cc
@@ -0,0 +1,122 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/favicon/ios/web_favicon_driver.h" + +#include "base/bind.h" +#include "components/favicon/core/favicon_url.h" +#include "components/favicon/ios/favicon_url_util.h" +#include "ios/web/public/browser_state.h" +#include "ios/web/public/favicon_status.h" +#include "ios/web/public/navigation_item.h" +#include "ios/web/public/navigation_manager.h" +#include "ios/web/public/web_state/web_state.h" +#include "ui/gfx/image/image.h" + +DEFINE_WEB_STATE_USER_DATA_KEY(favicon::WebFaviconDriver); + +namespace favicon { + +// static +void WebFaviconDriver::CreateForWebState( + web::WebState* web_state, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model) { + if (FromWebState(web_state)) + return; + + web_state->SetUserData(UserDataKey(), + new WebFaviconDriver(web_state, favicon_service, + history_service, bookmark_model)); +} + +gfx::Image WebFaviconDriver::GetFavicon() const { + web::NavigationItem* item = + web_state()->GetNavigationManager()->GetLastCommittedItem(); + return item ? item->GetFavicon().image : gfx::Image(); +} + +bool WebFaviconDriver::FaviconIsValid() const { + web::NavigationItem* item = + web_state()->GetNavigationManager()->GetLastCommittedItem(); + return item ? item->GetFavicon().valid : false; +} + +int WebFaviconDriver::StartDownload(const GURL& url, int max_image_size) { + if (WasUnableToDownloadFavicon(url)) { + DVLOG(1) << "Skip Failed FavIcon: " << url; + return 0; + } + + return web_state()->DownloadImage( + url, true, max_image_size, false, + base::Bind(&FaviconDriverImpl::DidDownloadFavicon, + base::Unretained(this))); +} + +bool WebFaviconDriver::IsOffTheRecord() { + DCHECK(web_state()); + return web_state()->GetBrowserState()->IsOffTheRecord(); +} + +GURL WebFaviconDriver::GetActiveURL() { + web::NavigationItem* item = + web_state()->GetNavigationManager()->GetVisibleItem(); + return item ? item->GetURL() : GURL(); +} + +base::string16 WebFaviconDriver::GetActiveTitle() { + web::NavigationItem* item = + web_state()->GetNavigationManager()->GetVisibleItem(); + return item ? item->GetTitle() : base::string16(); +} + +bool WebFaviconDriver::GetActiveFaviconValidity() { + return GetFaviconStatus().valid; +} + +void WebFaviconDriver::SetActiveFaviconValidity(bool validity) { + GetFaviconStatus().valid = validity; +} + +GURL WebFaviconDriver::GetActiveFaviconURL() { + return GetFaviconStatus().url; +} + +void WebFaviconDriver::SetActiveFaviconURL(const GURL& url) { + GetFaviconStatus().url = url; +} + +gfx::Image WebFaviconDriver::GetActiveFaviconImage() { + return GetFaviconStatus().image; +} + +void WebFaviconDriver::SetActiveFaviconImage(const gfx::Image& image) { + GetFaviconStatus().image = image; +} + +web::FaviconStatus& WebFaviconDriver::GetFaviconStatus() { + DCHECK(web_state()->GetNavigationManager()->GetVisibleItem()); + return web_state()->GetNavigationManager()->GetVisibleItem()->GetFavicon(); +} + +WebFaviconDriver::WebFaviconDriver(web::WebState* web_state, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model) + : web::WebStateObserver(web_state), + FaviconDriverImpl(favicon_service, history_service, bookmark_model) { +} + +WebFaviconDriver::~WebFaviconDriver() { +} + +void WebFaviconDriver::FaviconURLUpdated( + const std::vector<web::FaviconURL>& candidates) { + DCHECK(!candidates.empty()); + OnUpdateFaviconURL(FaviconURLsFromWebFaviconURLs(candidates)); +} + +} // namespace favicon
diff --git a/components/favicon/ios/web_favicon_driver.h b/components/favicon/ios/web_favicon_driver.h new file mode 100644 index 0000000..343d2be --- /dev/null +++ b/components/favicon/ios/web_favicon_driver.h
@@ -0,0 +1,66 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_FAVICON_IOS_WEB_FAVICON_DRIVER_H_ +#define COMPONENTS_FAVICON_IOS_WEB_FAVICON_DRIVER_H_ + +#include "components/favicon/core/favicon_driver_impl.h" +#include "ios/web/public/web_state/web_state_observer.h" +#include "ios/web/public/web_state/web_state_user_data.h" + +namespace web { +struct FaviconStatus; +class WebState; +} + +namespace favicon { + +// WebFaviconDriver is an implementation of FaviconDriver that listen to +// WebState events to start download of favicons and to get informed when the +// favicon download has completed. +class WebFaviconDriver : public web::WebStateObserver, + public web::WebStateUserData<WebFaviconDriver>, + public FaviconDriverImpl { + public: + static void CreateForWebState(web::WebState* web_state, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model); + + // FaviconDriver implementation. + gfx::Image GetFavicon() const override; + bool FaviconIsValid() const override; + int StartDownload(const GURL& url, int max_bitmap_size) override; + bool IsOffTheRecord() override; + GURL GetActiveURL() override; + base::string16 GetActiveTitle() override; + bool GetActiveFaviconValidity() override; + void SetActiveFaviconValidity(bool valid) override; + GURL GetActiveFaviconURL() override; + void SetActiveFaviconURL(const GURL& url) override; + gfx::Image GetActiveFaviconImage() override; + void SetActiveFaviconImage(const gfx::Image& image) override; + + private: + friend class web::WebStateUserData<WebFaviconDriver>; + + WebFaviconDriver(web::WebState* web_state, + FaviconService* favicon_service, + history::HistoryService* history_service, + bookmarks::BookmarkModel* bookmark_model); + ~WebFaviconDriver() override; + + // web::WebStateObserver implementation. + void FaviconURLUpdated( + const std::vector<web::FaviconURL>& candidates) override; + + // Returns the active navigation entry's favicon. + web::FaviconStatus& GetFaviconStatus(); + + DISALLOW_COPY_AND_ASSIGN(WebFaviconDriver); +}; + +} // namespace favicon + +#endif // COMPONENTS_FAVICON_IOS_WEB_FAVICON_DRIVER_H_
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index c257a76..4abcca4 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -1769,19 +1769,6 @@ ScheduleCommit(); } -void HistoryBackend::CloneFavicons(const GURL& old_page_url, - const GURL& new_page_url) { - if (!thumbnail_db_) - return; - - // Prevent cross-domain cloning. - if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) - return; - - thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); - ScheduleCommit(); -} - void HistoryBackend::SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) { if (!db_ || !thumbnail_db_)
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index 6c54b459..9a58cd4c 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -300,8 +300,6 @@ void SetFaviconsOutOfDateForPage(const GURL& page_url); - void CloneFavicons(const GURL& old_page_url, const GURL& new_page_url); - void SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage); @@ -505,8 +503,6 @@ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetFaviconsFromDBExpired); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, UpdateFaviconMappingsAndFetchNoDB); - FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, - CloneFaviconIsRestrictedToSameDomain); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, QueryFilteredURLs); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, UpdateVisitDuration); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, ExpireHistoryForTimes);
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index 296f833..238b682 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -622,15 +622,6 @@ history_backend_.get(), page_url)); } -void HistoryService::CloneFavicons(const GURL& old_page_url, - const GURL& new_page_url) { - DCHECK(thread_) << "History service being called after cleanup"; - DCHECK(thread_checker_.CalledOnValidThread()); - ScheduleTask(PRIORITY_NORMAL, - base::Bind(&HistoryBackend::CloneFavicons, - history_backend_.get(), old_page_url, new_page_url)); -} - void HistoryService::SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) { DCHECK(thread_) << "History service being called after cleanup";
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h index 7d7b00c..aaab5f3 100644 --- a/components/history/core/browser/history_service.h +++ b/components/history/core/browser/history_service.h
@@ -748,10 +748,6 @@ // of date. void SetFaviconsOutOfDateForPage(const GURL& page_url); - // Used by the FaviconService to clone favicons from one page to another, - // provided that other page does not already have favicons. - void CloneFavicons(const GURL& old_page_url, const GURL& new_page_url); - // Used by the FaviconService for importing many favicons for many pages at // once. The pages must exist, any favicon sets for unknown pages will be // discarded. Existing favicons will not be overwritten.
diff --git a/components/history/core/browser/thumbnail_database.cc b/components/history/core/browser/thumbnail_database.cc index 45bf299..e1579f9a 100644 --- a/components/history/core/browser/thumbnail_database.cc +++ b/components/history/core/browser/thumbnail_database.cc
@@ -1035,16 +1035,6 @@ return db_.GetLastInsertRowId(); } -bool ThumbnailDatabase::UpdateIconMapping(IconMappingID mapping_id, - favicon_base::FaviconID icon_id) { - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "UPDATE icon_mapping SET icon_id=? WHERE id=?")); - statement.BindInt64(0, icon_id); - statement.BindInt64(1, mapping_id); - - return statement.Run(); -} - bool ThumbnailDatabase::DeleteIconMappings(const GURL& page_url) { sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, "DELETE FROM icon_mapping WHERE page_url = ?")); @@ -1070,29 +1060,6 @@ return statement.Step(); } -bool ThumbnailDatabase::CloneIconMappings(const GURL& old_page_url, - const GURL& new_page_url) { - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "SELECT icon_id FROM icon_mapping " - "WHERE page_url=?")); - if (!statement.is_valid()) - return false; - - // Do nothing if there are existing bindings - statement.BindString(0, URLDatabase::GURLToDatabaseURL(new_page_url)); - if (statement.Step()) - return true; - - statement.Assign(db_.GetCachedStatement(SQL_FROM_HERE, - "INSERT INTO icon_mapping (page_url, icon_id) " - "SELECT ?, icon_id FROM icon_mapping " - "WHERE page_url = ?")); - - statement.BindString(0, URLDatabase::GURLToDatabaseURL(new_page_url)); - statement.BindString(1, URLDatabase::GURLToDatabaseURL(old_page_url)); - return statement.Run(); -} - bool ThumbnailDatabase::InitIconMappingEnumerator( favicon_base::IconType type, IconMappingEnumerator* enumerator) {
diff --git a/components/history/core/browser/thumbnail_database.h b/components/history/core/browser/thumbnail_database.h index c3c2927..e75b495 100644 --- a/components/history/core/browser/thumbnail_database.h +++ b/components/history/core/browser/thumbnail_database.h
@@ -190,12 +190,6 @@ IconMappingID AddIconMapping(const GURL& page_url, favicon_base::FaviconID icon_id); - // Updates the page and icon mapping for the given mapping_id with the given - // icon_id. - // Returns true if the update succeeded. - bool UpdateIconMapping(IconMappingID mapping_id, - favicon_base::FaviconID icon_id); - // Deletes the icon mapping entries for the given page url. // Returns true if the deletion succeeded. bool DeleteIconMappings(const GURL& page_url); @@ -207,10 +201,6 @@ // Checks whether a favicon is used by any URLs in the database. bool HasMappingFor(favicon_base::FaviconID id); - // Clones the existing mappings from |old_page_url| if |new_page_url| has no - // mappings. Otherwise, will leave mappings alone. - bool CloneIconMappings(const GURL& old_page_url, const GURL& new_page_url); - // The class to enumerate icon mappings. Use InitIconMappingEnumerator to // initialize. class IconMappingEnumerator {
diff --git a/components/metrics.gypi b/components/metrics.gypi index f0d3f41..ddad096 100644 --- a/components/metrics.gypi +++ b/components/metrics.gypi
@@ -37,8 +37,6 @@ 'metrics/daily_event.h', 'metrics/histogram_encoder.cc', 'metrics/histogram_encoder.h', - 'metrics/histogram_manager.cc', - 'metrics/histogram_manager.h', 'metrics/machine_id_provider.h', 'metrics/machine_id_provider_stub.cc', 'metrics/machine_id_provider_win.cc',
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 8a3e0cc..1c7301ca2 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -19,8 +19,6 @@ "daily_event.h", "histogram_encoder.cc", "histogram_encoder.h", - "histogram_manager.cc", - "histogram_manager.h", "machine_id_provider.h", "machine_id_provider_stub.cc", "machine_id_provider_win.cc", @@ -172,7 +170,6 @@ "compression_utils_unittest.cc", "daily_event_unittest.cc", "histogram_encoder_unittest.cc", - "histogram_manager_unittest.cc", "machine_id_provider_win_unittest.cc", "metrics_hashes_unittest.cc", "metrics_log_manager_unittest.cc",
diff --git a/components/onc/docs/onc_spec.html b/components/onc/docs/onc_spec.html index a0b89ab..e01186e 100644 --- a/components/onc/docs/onc_spec.html +++ b/components/onc/docs/onc_spec.html
@@ -1032,6 +1032,17 @@ </p> <dl class="field_list"> + <dt class="field">LcpEchoDisabled</dt> + <dd> + <span class="field_meta"> + (optional, defaults to <span class="value">false</span>) + <span class="type">boolean</span> + </span> + Disable L2TP connection monitoring via PPP LCP frames. This + allows the VPN client to work around server implementations + that do not support the LCP echo feature. + </dd> + <dt class="field">Password</dt> <dd> <span class="field_meta">
diff --git a/components/open_from_clipboard/clipboard_url_provider.cc b/components/open_from_clipboard/clipboard_url_provider.cc index 33fdf38..8590784f 100644 --- a/components/open_from_clipboard/clipboard_url_provider.cc +++ b/components/open_from_clipboard/clipboard_url_provider.cc
@@ -31,6 +31,8 @@ bool minimal_changes, bool called_due_to_focus) { matches_.clear(); + if (!called_due_to_focus) + return; // Attempt to add an AutocompleteMatch only if the user has not entered // anything in the omnibox. if (input.cursor_position() == base::string16::npos) {
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc index e9b87329..c45cc5f4 100644 --- a/components/password_manager/core/browser/login_database_unittest.cc +++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -1141,7 +1141,7 @@ void DestroyDatabase() { if (!database_path_.empty()) - base::DeleteFile(database_path_, false); + sql::Connection::Delete(database_path_); } // Returns an empty vector on failure. Otherwise returns the values of the
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 8f23055..64ade29c 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -92,6 +92,9 @@ bool ssl_valid) : best_matches_deleter_(&best_matches_), observed_form_(CopyAndModifySSLValidity(observed_form, ssl_valid)), + provisionally_saved_form_(nullptr), + other_possible_username_action_( + PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES), is_new_login_(true), has_generated_password_(false), password_manager_(password_manager), @@ -258,7 +261,7 @@ } bool PasswordFormManager::HasValidPasswordForm() const { - DCHECK_EQ(state_, POST_MATCHING_PHASE); + DCHECK(state_ == MATCHING_PHASE || state_ == POST_MATCHING_PHASE) << state_; // Non-HTML password forms (primarily HTTP and FTP autentication) // do not contain username_element and password_element values. if (observed_form_.scheme != PasswordForm::SCHEME_HTML) @@ -270,120 +273,13 @@ void PasswordFormManager::ProvisionallySave( const PasswordForm& credentials, OtherPossibleUsernamesAction action) { - DCHECK_EQ(state_, POST_MATCHING_PHASE); + DCHECK(state_ == MATCHING_PHASE || state_ == POST_MATCHING_PHASE) << state_; DCHECK_NE(RESULT_NO_MATCH, DoesManage(credentials)); + provisionally_saved_form_.reset(new PasswordForm(credentials)); + other_possible_username_action_ = action; - base::string16 password_to_save(PasswordToSave(credentials)); - - // Make sure the important fields stay the same as the initially observed or - // autofilled ones, as they may have changed if the user experienced a login - // failure. - // Look for these credentials in the list containing auto-fill entries. - PasswordFormMap::const_iterator it = - best_matches_.find(credentials.username_value); - if (it != best_matches_.end()) { - // The user signed in with a login we autofilled. - pending_credentials_ = *it->second; - bool password_changed = - pending_credentials_.password_value != password_to_save; - if (IsPendingCredentialsPublicSuffixMatch()) { - // If the autofilled credentials were only a PSL match, store a copy with - // the current origin and signon realm. This ensures that on the next - // visit, a precise match is found. - is_new_login_ = true; - user_action_ = password_changed ? kUserActionChoosePslMatch - : kUserActionOverridePassword; - - // Update credential to reflect that it has been used for submission. - // If this isn't updated, then password generation uploads are off for - // sites where PSL matching is required to fill the login form, as two - // PASSWORD votes are uploaded per saved password instead of one. - // - // TODO(gcasto): It would be nice if other state were shared such that if - // say a password was updated on one match it would update on all related - // passwords. This is a much larger change. - UpdateMetadataForUsage(pending_credentials_); - - // Normally, the copy of the PSL matched credentials, adapted for the - // current domain, is saved automatically without asking the user, because - // the copy likely represents the same account, i.e., the one for which - // the user already agreed to store a password. - // - // However, if the user changes the suggested password, it might indicate - // that the autofilled credentials and |credentials| actually correspond - // to two different accounts (see http://crbug.com/385619). In that case - // the user should be asked again before saving the password. This is - // ensured by clearing |original_signon_realm| on |pending_credentials_|, - // which unmarks it as a PSL match. - // - // There is still the edge case when the autofilled credentials represent - // the same account as |credentials| but the stored password was out of - // date. In that case, the user just had to manually enter the new - // password, which is now in |credentials|. The best thing would be to - // save automatically, and also update the original credentials. However, - // we have no way to tell if this is the case. This will likely happen - // infrequently, and the inconvenience put on the user by asking them is - // not significant, so we are fine with asking here again. - if (password_changed) { - pending_credentials_.original_signon_realm.clear(); - DCHECK(!IsPendingCredentialsPublicSuffixMatch()); - } - } else { // Not a PSL match. - is_new_login_ = false; - if (password_changed) - user_action_ = kUserActionOverridePassword; - } - } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES && - UpdatePendingCredentialsIfOtherPossibleUsername( - credentials.username_value)) { - // |pending_credentials_| is now set. Note we don't update - // |pending_credentials_.username_value| to |credentials.username_value| - // yet because we need to keep the original username to modify the stored - // credential. - selected_username_ = credentials.username_value; - is_new_login_ = false; - } else { - // User typed in a new, unknown username. - user_action_ = kUserActionOverrideUsernameAndPassword; - pending_credentials_ = observed_form_; - if (credentials.was_parsed_using_autofill_predictions) - pending_credentials_.username_element = credentials.username_element; - pending_credentials_.username_value = credentials.username_value; - pending_credentials_.other_possible_usernames = - credentials.other_possible_usernames; - - // The password value will be filled in later, remove any garbage for now. - pending_credentials_.password_value.clear(); - pending_credentials_.new_password_value.clear(); - - // If this was a sign-up or change password form, the names of the elements - // are likely different than those on a login form, so do not bother saving - // them. We will fill them with meaningful values in UpdateLogin() when the - // user goes onto a real login form for the first time. - if (!credentials.new_password_element.empty()) { - pending_credentials_.password_element.clear(); - pending_credentials_.new_password_element.clear(); - } - } - - pending_credentials_.action = credentials.action; - // If the user selected credentials we autofilled from a PasswordForm - // that contained no action URL (IE6/7 imported passwords, for example), - // bless it with the action URL from the observed form. See bug 1107719. - if (pending_credentials_.action.is_empty()) - pending_credentials_.action = observed_form_.action; - - pending_credentials_.password_value = password_to_save; - pending_credentials_.preferred = credentials.preferred; - - if (user_action_ == kUserActionOverridePassword && - pending_credentials_.type == PasswordForm::TYPE_GENERATED && - !has_generated_password_) { - LogPasswordGenerationSubmissionEvent(PASSWORD_OVERRIDDEN); - } - - if (has_generated_password_) - pending_credentials_.type = PasswordForm::TYPE_GENERATED; + if (HasCompletedMatching()) + CreatePendingCredentials(); } void PasswordFormManager::Save() { @@ -623,6 +519,11 @@ OnRequestDone(results.Pass()); state_ = POST_MATCHING_PHASE; + // If password store was slow and provisionally saved form is already here + // then create pending credentials (see http://crbug.com/470322). + if (provisionally_saved_form_) + CreatePendingCredentials(); + if (manager_action_ != kManagerActionBlacklisted) { for (auto const& driver : drivers_) ProcessFrame(driver); @@ -869,6 +770,128 @@ return success; } +void PasswordFormManager::CreatePendingCredentials() { + DCHECK(provisionally_saved_form_); + base::string16 password_to_save(PasswordToSave(*provisionally_saved_form_)); + + // Make sure the important fields stay the same as the initially observed or + // autofilled ones, as they may have changed if the user experienced a login + // failure. + // Look for these credentials in the list containing auto-fill entries. + PasswordFormMap::const_iterator it = + best_matches_.find(provisionally_saved_form_->username_value); + if (it != best_matches_.end()) { + // The user signed in with a login we autofilled. + pending_credentials_ = *it->second; + bool password_changed = + pending_credentials_.password_value != password_to_save; + if (IsPendingCredentialsPublicSuffixMatch()) { + // If the autofilled credentials were only a PSL match, store a copy with + // the current origin and signon realm. This ensures that on the next + // visit, a precise match is found. + is_new_login_ = true; + user_action_ = password_changed ? kUserActionChoosePslMatch + : kUserActionOverridePassword; + + // Update credential to reflect that it has been used for submission. + // If this isn't updated, then password generation uploads are off for + // sites where PSL matching is required to fill the login form, as two + // PASSWORD votes are uploaded per saved password instead of one. + // + // TODO(gcasto): It would be nice if other state were shared such that if + // say a password was updated on one match it would update on all related + // passwords. This is a much larger change. + UpdateMetadataForUsage(pending_credentials_); + + // Normally, the copy of the PSL matched credentials, adapted for the + // current domain, is saved automatically without asking the user, because + // the copy likely represents the same account, i.e., the one for which + // the user already agreed to store a password. + // + // However, if the user changes the suggested password, it might indicate + // that the autofilled credentials and |provisionally_saved_form_| + // actually correspond to two different accounts (see + // http://crbug.com/385619). In that case the user should be asked again + // before saving the password. This is ensured by clearing + // |original_signon_realm| on |pending_credentials_|, which unmarks it as + // a PSL match. + // + // There is still the edge case when the autofilled credentials represent + // the same account as |provisionally_saved_form_| but the stored password + // was out of date. In that case, the user just had to manually enter the + // new password, which is now in |provisionally_saved_form_|. The best + // thing would be to save automatically, and also update the original + // credentials. However, we have no way to tell if this is the case. + // This will likely happen infrequently, and the inconvenience put on the + // user by asking them is not significant, so we are fine with asking + // here again. + if (password_changed) { + pending_credentials_.original_signon_realm.clear(); + DCHECK(!IsPendingCredentialsPublicSuffixMatch()); + } + } else { // Not a PSL match. + is_new_login_ = false; + if (password_changed) + user_action_ = kUserActionOverridePassword; + } + } else if (other_possible_username_action_ == + ALLOW_OTHER_POSSIBLE_USERNAMES && + UpdatePendingCredentialsIfOtherPossibleUsername( + provisionally_saved_form_->username_value)) { + // |pending_credentials_| is now set. Note we don't update + // |pending_credentials_.username_value| to |credentials.username_value| + // yet because we need to keep the original username to modify the stored + // credential. + selected_username_ = provisionally_saved_form_->username_value; + is_new_login_ = false; + } else { + // User typed in a new, unknown username. + user_action_ = kUserActionOverrideUsernameAndPassword; + pending_credentials_ = observed_form_; + if (provisionally_saved_form_->was_parsed_using_autofill_predictions) + pending_credentials_.username_element = + provisionally_saved_form_->username_element; + pending_credentials_.username_value = + provisionally_saved_form_->username_value; + pending_credentials_.other_possible_usernames = + provisionally_saved_form_->other_possible_usernames; + + // The password value will be filled in later, remove any garbage for now. + pending_credentials_.password_value.clear(); + pending_credentials_.new_password_value.clear(); + + // If this was a sign-up or change password form, the names of the elements + // are likely different than those on a login form, so do not bother saving + // them. We will fill them with meaningful values in UpdateLogin() when the + // user goes onto a real login form for the first time. + if (!provisionally_saved_form_->new_password_element.empty()) { + pending_credentials_.password_element.clear(); + pending_credentials_.new_password_element.clear(); + } + } + + pending_credentials_.action = provisionally_saved_form_->action; + // If the user selected credentials we autofilled from a PasswordForm + // that contained no action URL (IE6/7 imported passwords, for example), + // bless it with the action URL from the observed form. See bug 1107719. + if (pending_credentials_.action.is_empty()) + pending_credentials_.action = observed_form_.action; + + pending_credentials_.password_value = password_to_save; + pending_credentials_.preferred = provisionally_saved_form_->preferred; + + if (user_action_ == kUserActionOverridePassword && + pending_credentials_.type == PasswordForm::TYPE_GENERATED && + !has_generated_password_) { + LogPasswordGenerationSubmissionEvent(PASSWORD_OVERRIDDEN); + } + + if (has_generated_password_) + pending_credentials_.type = PasswordForm::TYPE_GENERATED; + + provisionally_saved_form_.reset(); +} + int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const { DCHECK_EQ(state_, MATCHING_PHASE); // For scoring of candidate login data:
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h index d7c49a8..2da08e0e 100644 --- a/components/password_manager/core/browser/password_form_manager.h +++ b/components/password_manager/core/browser/password_form_manager.h
@@ -200,7 +200,6 @@ } #endif - protected: const autofill::PasswordForm& observed_form() const { return observed_form_; } private: @@ -326,6 +325,10 @@ bool UploadPasswordForm(const autofill::FormData& form_data, const autofill::ServerFieldType& password_type); + // Create pending credentials from provisionally saved form and forms received + // from password store. + void CreatePendingCredentials(); + // Set of PasswordForms from the DB that best match the form // being managed by this. Use a map instead of vector, because we most // frequently require lookups by username value in IsNewLogin. @@ -338,6 +341,12 @@ // The PasswordForm from the page or dialog managed by |this|. const autofill::PasswordForm observed_form_; + // Stores provisionally saved form until |pending_credentials_| is created. + scoped_ptr<const autofill::PasswordForm> provisionally_saved_form_; + // Stores if for creating |pending_credentials_| other possible usernames + // option should apply. + OtherPossibleUsernamesAction other_possible_username_action_; + // The origin url path of observed_form_ tokenized, for convenience when // scoring. std::vector<std::string> form_path_tokens_;
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 5d8bd589..2e619e04 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -178,7 +178,6 @@ // Below, "matching" is in DoesManage-sense and "not ready" in // !HasCompletedMatching sense. We keep track of such PasswordFormManager // instances for UMA. - bool has_found_matching_managers_which_were_not_ready = false; for (ScopedVector<PasswordFormManager>::iterator iter = pending_login_managers_.begin(); iter != pending_login_managers_.end(); ++iter) { @@ -195,11 +194,6 @@ continue; } - if (!(*iter)->HasCompletedMatching()) { - has_found_matching_managers_which_were_not_ready = true; - continue; - } - if (result == PasswordFormManager::RESULT_COMPLETE_MATCH) { // If we find a manager that exactly matches the submitted form including // the action URL, exit the loop. @@ -241,25 +235,11 @@ // |manager|. manager.reset(*matched_manager_it); pending_login_managers_.weak_erase(matched_manager_it); - } else if (has_found_matching_managers_which_were_not_ready) { - // We found some managers, but none finished matching yet. The user has - // tried to submit credentials before we had time to even find matching - // results for the given form and autofill. If this is the case, we just - // give up. - RecordFailure(MATCHING_NOT_COMPLETE, form.origin, logger.get()); - return; } else { RecordFailure(NO_MATCHING_FORM, form.origin, logger.get()); return; } - // Also get out of here if the user told us to 'never remember' passwords for - // this form. - if (manager->IsBlacklisted()) { - RecordFailure(FORM_BLACKLISTED, form.origin, logger.get()); - return; - } - // Bail if we're missing any of the necessary form components. if (!manager->HasValidPasswordForm()) { RecordFailure(INVALID_FORM, form.origin, logger.get()); @@ -467,6 +447,26 @@ return; } + if (!provisional_save_manager_->HasCompletedMatching()) { + // We have a provisional save manager, but it didn't finish matching yet. + // We just give up. + RecordFailure(MATCHING_NOT_COMPLETE, + provisional_save_manager_->observed_form().origin, + logger.get()); + provisional_save_manager_.reset(); + return; + } + + // Also get out of here if the user told us to 'never remember' passwords for + // this form. + if (provisional_save_manager_->IsBlacklisted()) { + RecordFailure(FORM_BLACKLISTED, + provisional_save_manager_->observed_form().origin, + logger.get()); + provisional_save_manager_.reset(); + return; + } + DCHECK(client_->IsSavingEnabledForCurrentPage()); // If the server throws an internal error, access denied page, page not
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index 9e787f5..4aa5524 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -36,7 +36,7 @@ class PasswordFormManager; // TODO(melandory): Separate the PasswordFormManager API interface and the -// implementation in two classes crbug/473184. +// implementation in two classes http://crbug.com/473184. // Per-tab password manager. Handles creation and management of UI elements, // receiving password form data from the renderer and managing the password
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 08b30bf2..e5746e54 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -25,6 +25,7 @@ using testing::_; using testing::AnyNumber; using testing::Exactly; +using testing::Invoke; using testing::Return; using testing::WithArg; @@ -1028,4 +1029,52 @@ form_to_save->Save(); } +TEST_F(PasswordManagerTest, SubmitNotFetchedFromStoreForm) { + // Test that observing a newly submitted form that is fetched after on submit + // shows the save password bar. + EXPECT_CALL(driver_, FillPasswordForm(_)).Times(Exactly(0)); + std::vector<PasswordForm> observed; + PasswordForm form(MakeSimpleForm()); + observed.push_back(form); + + PasswordStoreConsumer* form_manager = nullptr; + // Do not call back from store after GetLogins is called. Instead, save the + // pointer to the form manager for calling back later. This emulates that + // PasswordStore does not manage to fetch a form till moment of submission. + ON_CALL(*store_, GetLogins(_, _, _)) + .WillByDefault(testing::SaveArg<2>(&form_manager)); + // The initial load. + manager()->OnPasswordFormsParsed(&driver_, observed); + // The initial layout. + manager()->OnPasswordFormsRendered(&driver_, observed, true); + ASSERT_TRUE(form_manager); + + // And the form submit contract is to call ProvisionallySavePassword. + manager()->ProvisionallySavePassword(form); + + // Emulate fetching password form from PasswordStore after submission but + // before post-navigation load. + form_manager->OnGetPasswordStoreResults( + ScopedVector<autofill::PasswordForm>()); + + scoped_ptr<PasswordFormManager> form_to_save; + EXPECT_CALL(client_, + PromptUserToSavePasswordPtr( + _, CredentialSourceType::CREDENTIAL_SOURCE_PASSWORD_MANAGER)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); + + // Now the password manager waits for the navigation to complete. + observed.clear(); + // The post-navigation load. + manager()->OnPasswordFormsParsed(&driver_, observed); + // The post-navigation layout. + manager()->OnPasswordFormsRendered(&driver_, observed, true); + + ASSERT_TRUE(form_to_save); + EXPECT_CALL(*store_, AddLogin(FormMatches(form))); + + // Simulate saving the form, as if the info bar was accepted. + form_to_save->Save(); +} + } // namespace password_manager
diff --git a/components/policy/proto/BUILD.gn b/components/policy/proto/BUILD.gn index cc84042..3b6a7b26 100644 --- a/components/policy/proto/BUILD.gn +++ b/components/policy/proto/BUILD.gn
@@ -4,7 +4,18 @@ import("//third_party/protobuf/proto_library.gni") -proto_library("proto") { +# The proto files need to be a component to avoid duplicate symbols the way the +# dependency structure is currently. Since proto_library generates a source +# set, here we link the result into a component. +component("proto") { + public_deps = [ + ":proto_internal", + ] +} + +proto_library("proto_internal") { + visibility = [ ":proto" ] + sources = [ "device_management_backend.proto", "policy_signing_key.proto",
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 4969430..8ef71a7 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -123,7 +123,7 @@ # persistent IDs for all fields (but not for groups!) are needed. These are # specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs, # because doing so would break the deployed wire format! -# For your editing convenience: highest ID currently used: 297 +# For your editing convenience: highest ID currently used: 298 # # Placeholders: # The following placeholder strings are automatically substituted: @@ -7306,6 +7306,21 @@ 'desc': '''If this policy is set to a blank string or not configured, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will not show an autocomplete option during user sign-in flow. If this policy is set to a string representing a domain name, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will show an autocomplete option during user sign-in allowing the user to type in only his user name without the domain name extension. The user will be able to overwrite this domain name extension.''', }, + { + 'name': 'ForceMaximizeOnFirstRun', + 'type': 'main', + 'schema': { 'type': 'boolean' }, + 'supported_on': ['chrome_os:43-'], + 'features': { + 'dynamic_refresh': False, + 'per_profile': True, + }, + 'example_value': True, + 'id': 298, + 'caption': '''Maximize the first browser window on first run''', + 'desc': '''If this policy is set to true, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will unconditionally maximize the the first window shown on first run. + If this policy is set to false or not configured, a heuristic will decide whether to maximize the first window shown, based on the screen size.''', + }, ], 'messages': { # Messages that are not associated to any policies.
diff --git a/components/proximity_auth.gypi b/components/proximity_auth.gypi index 1541ddb..fe5f3be2 100644 --- a/components/proximity_auth.gypi +++ b/components/proximity_auth.gypi
@@ -16,8 +16,6 @@ '../net/net.gyp:net', ], 'sources': [ - "proximity_auth/base64url.cc", - "proximity_auth/base64url.h", "proximity_auth/bluetooth_connection.cc", "proximity_auth/bluetooth_connection.h", "proximity_auth/bluetooth_connection_finder.cc", @@ -71,15 +69,16 @@ '../net/net.gyp:net', ], 'sources': [ + "proximity_auth/cryptauth/base64url.cc", + "proximity_auth/cryptauth/base64url.h", "proximity_auth/cryptauth/cryptauth_access_token_fetcher.h", - "proximity_auth/cryptauth/cryptauth_account_token_fetcher.cc", - "proximity_auth/cryptauth/cryptauth_account_token_fetcher.h", + "proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.cc", + "proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h", "proximity_auth/cryptauth/cryptauth_api_call_flow.cc", "proximity_auth/cryptauth/cryptauth_api_call_flow.h", - "proximity_auth/cryptauth/cryptauth_client.cc", "proximity_auth/cryptauth/cryptauth_client.h", - "proximity_auth/cryptauth/cryptauth_client_factory.cc", - "proximity_auth/cryptauth/cryptauth_client_factory.h", + "proximity_auth/cryptauth/cryptauth_client_impl.cc", + "proximity_auth/cryptauth/cryptauth_client_impl.h", "proximity_auth/cryptauth/cryptauth_enrollment_utils.cc", "proximity_auth/cryptauth/cryptauth_enrollment_utils.h", "proximity_auth/cryptauth/secure_message_delegate.cc",
diff --git a/components/proximity_auth/BUILD.gn b/components/proximity_auth/BUILD.gn index 84f827b..380459e6 100644 --- a/components/proximity_auth/BUILD.gn +++ b/components/proximity_auth/BUILD.gn
@@ -6,8 +6,6 @@ source_set("proximity_auth") { sources = [ - "base64url.cc", - "base64url.h", "bluetooth_connection.cc", "bluetooth_connection.h", "bluetooth_connection_finder.cc", @@ -44,7 +42,6 @@ source_set("unit_tests") { testonly = true sources = [ - "base64url_unittest.cc", "bluetooth_connection_finder_unittest.cc", "bluetooth_connection_unittest.cc", "client_unittest.cc",
diff --git a/components/proximity_auth/client.cc b/components/proximity_auth/client.cc index 586a4b7..016c505 100644 --- a/components/proximity_auth/client.cc +++ b/components/proximity_auth/client.cc
@@ -7,9 +7,9 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/values.h" -#include "components/proximity_auth/base64url.h" #include "components/proximity_auth/client_observer.h" #include "components/proximity_auth/connection.h" +#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/remote_status_update.h" #include "components/proximity_auth/secure_context.h" #include "components/proximity_auth/wire_message.h"
diff --git a/components/proximity_auth/cryptauth/BUILD.gn b/components/proximity_auth/cryptauth/BUILD.gn index e496151..bf255eb6 100644 --- a/components/proximity_auth/cryptauth/BUILD.gn +++ b/components/proximity_auth/cryptauth/BUILD.gn
@@ -4,15 +4,16 @@ source_set("cryptauth") { sources = [ + "base64url.cc", + "base64url.h", "cryptauth_access_token_fetcher.h", - "cryptauth_account_token_fetcher.cc", - "cryptauth_account_token_fetcher.h", + "cryptauth_access_token_fetcher_impl.cc", + "cryptauth_access_token_fetcher_impl.h", "cryptauth_api_call_flow.cc", "cryptauth_api_call_flow.h", - "cryptauth_client.cc", "cryptauth_client.h", - "cryptauth_client_factory.cc", - "cryptauth_client_factory.h", + "cryptauth_client_impl.cc", + "cryptauth_client_impl.h", "cryptauth_enrollment_utils.cc", "cryptauth_enrollment_utils.h", "secure_message_delegate.cc", @@ -49,9 +50,10 @@ source_set("unit_tests") { testonly = true sources = [ - "cryptauth_account_token_fetcher_unittest.cc", + "base64url_unittest.cc", + "cryptauth_access_token_fetcher_impl_unittest.cc", "cryptauth_api_call_flow_unittest.cc", - "cryptauth_client_unittest.cc", + "cryptauth_client_impl_unittest.cc", "fake_secure_message_delegate_unittest.cc", ]
diff --git a/components/proximity_auth/base64url.cc b/components/proximity_auth/cryptauth/base64url.cc similarity index 94% rename from components/proximity_auth/base64url.cc rename to components/proximity_auth/cryptauth/base64url.cc index ae6ee9d..a38043f 100644 --- a/components/proximity_auth/base64url.cc +++ b/components/proximity_auth/cryptauth/base64url.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/proximity_auth/base64url.h" +#include "components/proximity_auth/cryptauth/base64url.h" #include "base/base64.h" #include "base/strings/string_util.h"
diff --git a/components/proximity_auth/base64url.h b/components/proximity_auth/cryptauth/base64url.h similarity index 90% rename from components/proximity_auth/base64url.h rename to components/proximity_auth/cryptauth/base64url.h index 63d4990..5317cd8 100644 --- a/components/proximity_auth/base64url.h +++ b/components/proximity_auth/cryptauth/base64url.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PROXIMITY_BASE64URL_H -#define COMPONENTS_PROXIMITY_BASE64URL_H +#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_BASE64URL_H +#define COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_BASE64URL_H #include <string>
diff --git a/components/proximity_auth/base64url_unittest.cc b/components/proximity_auth/cryptauth/base64url_unittest.cc similarity index 97% rename from components/proximity_auth/base64url_unittest.cc rename to components/proximity_auth/cryptauth/base64url_unittest.cc index 9461858..88fd16c 100644 --- a/components/proximity_auth/base64url_unittest.cc +++ b/components/proximity_auth/cryptauth/base64url_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/proximity_auth/base64url.h" +#include "components/proximity_auth/cryptauth/base64url.h" #include "base/base64.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h index 6287dfeab..3c428628 100644 --- a/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h +++ b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_ACCESS_TOKEN_FETCHER_H -#define COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_ACCESS_TOKEN_FETCHER_H +#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_ACCESS_TOKEN_FETCHER_H +#define COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_ACCESS_TOKEN_FETCHER_H #include <string> @@ -27,4 +27,4 @@ } // namespace proximity_auth -#endif // COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_ACCESS_TOKEN_FETCHER_H +#endif // COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_ACCESS_TOKEN_FETCHER_H
diff --git a/components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.cc b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.cc similarity index 75% rename from components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.cc rename to components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.cc index f02ee68..294b2ba 100644 --- a/components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.cc +++ b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h" +#include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h" namespace proximity_auth { @@ -17,19 +17,19 @@ } // namespace -CryptAuthAccountTokenFetcher::CryptAuthAccountTokenFetcher( +CryptAuthAccessTokenFetcherImpl::CryptAuthAccessTokenFetcherImpl( OAuth2TokenService* token_service, const std::string& account_id) - : OAuth2TokenService::Consumer("cryptauth_account_token_fetcher"), + : OAuth2TokenService::Consumer("cryptauth_access_token_fetcher"), token_service_(token_service), account_id_(account_id), fetch_started_(false) { } -CryptAuthAccountTokenFetcher::~CryptAuthAccountTokenFetcher() { +CryptAuthAccessTokenFetcherImpl::~CryptAuthAccessTokenFetcherImpl() { } -void CryptAuthAccountTokenFetcher::FetchAccessToken( +void CryptAuthAccessTokenFetcherImpl::FetchAccessToken( const AccessTokenCallback& callback) { if (fetch_started_) { LOG(WARNING) << "Create an instance for each token fetched. Do not reuse."; @@ -44,14 +44,14 @@ token_request_ = token_service_->StartRequest(account_id_, GetScopes(), this); } -void CryptAuthAccountTokenFetcher::OnGetTokenSuccess( +void CryptAuthAccessTokenFetcherImpl::OnGetTokenSuccess( const OAuth2TokenService::Request* request, const std::string& access_token, const base::Time& expiration_time) { callback_.Run(access_token); } -void CryptAuthAccountTokenFetcher::OnGetTokenFailure( +void CryptAuthAccessTokenFetcherImpl::OnGetTokenFailure( const OAuth2TokenService::Request* request, const GoogleServiceAuthError& error) { callback_.Run(std::string());
diff --git a/components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h similarity index 71% rename from components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h rename to components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h index 49ce4b0..af798ae 100644 --- a/components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h +++ b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_ACCOUNT_TOKEN_FETCHER_IMPL_H -#define COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_ACCOUNT_TOKEN_FETCHER_IMPL_H +#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_ACCESS_TOKEN_FETCHER_IMPL_H +#define COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_ACCESS_TOKEN_FETCHER_IMPL_H #include "base/callback.h" #include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" @@ -13,13 +13,13 @@ // Implementation of CryptAuthAccessTokenFetcher fetching an access token for a // given account using the provided OAuth2TokenService. -class CryptAuthAccountTokenFetcher : public CryptAuthAccessTokenFetcher, - public OAuth2TokenService::Consumer { +class CryptAuthAccessTokenFetcherImpl : public CryptAuthAccessTokenFetcher, + public OAuth2TokenService::Consumer { public: // |token_service| is not owned, and must outlive this object. - CryptAuthAccountTokenFetcher(OAuth2TokenService* token_service, - const std::string& account_id); - ~CryptAuthAccountTokenFetcher() override; + CryptAuthAccessTokenFetcherImpl(OAuth2TokenService* token_service, + const std::string& account_id); + ~CryptAuthAccessTokenFetcherImpl() override; // CryptAuthAccessTokenFetcher: void FetchAccessToken(const AccessTokenCallback& callback) override; @@ -48,9 +48,9 @@ // Callback to invoke when the token fetch succeeds or fails. AccessTokenCallback callback_; - DISALLOW_COPY_AND_ASSIGN(CryptAuthAccountTokenFetcher); + DISALLOW_COPY_AND_ASSIGN(CryptAuthAccessTokenFetcherImpl); }; } // namespace proximity_auth -#endif // COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_ACCESS_TOKEN_FETCHER_IMPL_H +#endif // COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_ACCESS_TOKEN_FETCHER_IMPL_H
diff --git a/components/proximity_auth/cryptauth/cryptauth_account_token_fetcher_unittest.cc b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl_unittest.cc similarity index 77% rename from components/proximity_auth/cryptauth/cryptauth_account_token_fetcher_unittest.cc rename to components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl_unittest.cc index 74fb5a35..3fa70a5 100644 --- a/components/proximity_auth/cryptauth/cryptauth_account_token_fetcher_unittest.cc +++ b/components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h" +#include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h" #include <string> @@ -25,20 +25,20 @@ } // namespace -class ProximityAuthCryptAuthAccountTokenFetcherTest : public testing::Test { +class ProximityAuthCryptAuthAccessTokenFetcherTest : public testing::Test { protected: - ProximityAuthCryptAuthAccountTokenFetcherTest() + ProximityAuthCryptAuthAccessTokenFetcherTest() : fetcher_(&token_service_, kAccountId) { token_service_.AddAccount(kAccountId); } FakeOAuth2TokenService token_service_; - CryptAuthAccountTokenFetcher fetcher_; + CryptAuthAccessTokenFetcherImpl fetcher_; - DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthAccountTokenFetcherTest); + DISALLOW_COPY_AND_ASSIGN(ProximityAuthCryptAuthAccessTokenFetcherTest); }; -TEST_F(ProximityAuthCryptAuthAccountTokenFetcherTest, FetchSuccess) { +TEST_F(ProximityAuthCryptAuthAccessTokenFetcherTest, FetchSuccess) { std::string result; fetcher_.FetchAccessToken(base::Bind(SaveAccessToken, &result)); token_service_.IssueAllTokensForAccount(kAccountId, kAccessToken, @@ -47,7 +47,7 @@ EXPECT_EQ(kAccessToken, result); } -TEST_F(ProximityAuthCryptAuthAccountTokenFetcherTest, FetchFailure) { +TEST_F(ProximityAuthCryptAuthAccessTokenFetcherTest, FetchFailure) { std::string result(kInvalidResult); fetcher_.FetchAccessToken(base::Bind(SaveAccessToken, &result)); token_service_.IssueErrorForAllPendingRequestsForAccount( @@ -57,7 +57,7 @@ EXPECT_EQ(std::string(), result); } -TEST_F(ProximityAuthCryptAuthAccountTokenFetcherTest, FetcherReuse) { +TEST_F(ProximityAuthCryptAuthAccessTokenFetcherTest, FetcherReuse) { std::string result1; fetcher_.FetchAccessToken(base::Bind(SaveAccessToken, &result1));
diff --git a/components/proximity_auth/cryptauth/cryptauth_api_call_flow.cc b/components/proximity_auth/cryptauth/cryptauth_api_call_flow.cc index 5700756..acefa12e 100644 --- a/components/proximity_auth/cryptauth/cryptauth_api_call_flow.cc +++ b/components/proximity_auth/cryptauth/cryptauth_api_call_flow.cc
@@ -17,18 +17,19 @@ } // namespace -CryptAuthApiCallFlow::CryptAuthApiCallFlow(const GURL& request_url) - : request_url_(request_url) { +CryptAuthApiCallFlow::CryptAuthApiCallFlow() { } CryptAuthApiCallFlow::~CryptAuthApiCallFlow() { } -void CryptAuthApiCallFlow::Start(net::URLRequestContextGetter* context, +void CryptAuthApiCallFlow::Start(const GURL& request_url, + net::URLRequestContextGetter* context, const std::string& access_token, const std::string& serialized_request, const ResultCallback& result_callback, const ErrorCallback& error_callback) { + request_url_ = request_url; serialized_request_ = serialized_request; result_callback_ = result_callback; error_callback_ = error_callback;
diff --git a/components/proximity_auth/cryptauth/cryptauth_api_call_flow.h b/components/proximity_auth/cryptauth/cryptauth_api_call_flow.h index 7625a23..f351aed 100644 --- a/components/proximity_auth/cryptauth/cryptauth_api_call_flow.h +++ b/components/proximity_auth/cryptauth/cryptauth_api_call_flow.h
@@ -22,17 +22,19 @@ ResultCallback; typedef base::Callback<void(const std::string& error_message)> ErrorCallback; - CryptAuthApiCallFlow(const GURL& request_url); + CryptAuthApiCallFlow(); ~CryptAuthApiCallFlow() override; // Starts the API call. + // request_url: The URL endpoint of the API request. // context: The URL context used to make the request. // access_token: The access token for whom to make the to make the request. // serialized_request: A serialized proto containing the request data. // result_callback: Called when the flow completes successfully with a // serialized response proto. // error_callback: Called when the flow completes with an error. - virtual void Start(net::URLRequestContextGetter* context, + virtual void Start(const GURL& request_url, + net::URLRequestContextGetter* context, const std::string& access_token, const std::string& serialized_request, const ResultCallback& result_callback, @@ -52,7 +54,7 @@ private: // The URL of the CryptAuth endpoint serving the request. - const GURL request_url_; + GURL request_url_; // Serialized request message proto that will be sent in the API request. std::string serialized_request_;
diff --git a/components/proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc b/components/proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc index 53417e72..8cc2384c 100644 --- a/components/proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc +++ b/components/proximity_auth/cryptauth/cryptauth_api_call_flow_unittest.cc
@@ -25,8 +25,7 @@ protected: ProximityAuthCryptAuthApiCallFlowTest() : url_request_context_getter_(new net::TestURLRequestContextGetter( - new base::TestSimpleTaskRunner())), - flow_(GURL(kRequestUrl)) {} + new base::TestSimpleTaskRunner())) {} void SetUp() override { // The TestURLFetcherFactory will override the global URLFetcherFactory for @@ -36,9 +35,8 @@ } void StartApiCallFlow() { - flow_.Start(url_request_context_getter_.get(), - "access_token", - kSerializedRequestProto, + flow_.Start(GURL(kRequestUrl), url_request_context_getter_.get(), + "access_token", kSerializedRequestProto, base::Bind(&ProximityAuthCryptAuthApiCallFlowTest::OnResult, base::Unretained(this)), base::Bind(&ProximityAuthCryptAuthApiCallFlowTest::OnError,
diff --git a/components/proximity_auth/cryptauth/cryptauth_client.h b/components/proximity_auth/cryptauth/cryptauth_client.h index 0e77e502..7dfa236b 100644 --- a/components/proximity_auth/cryptauth/cryptauth_client.h +++ b/components/proximity_auth/cryptauth/cryptauth_client.h
@@ -2,146 +2,93 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_CLIENT_H -#define COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_CLIENT_H +#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_CLIENT_H +#define COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_CLIENT_H -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" -#include "net/url_request/url_request_context_getter.h" -#include "url/gurl.h" + +namespace net { +class URLRequestContextGetter; +} namespace proximity_auth { class CryptAuthAccessTokenFetcher; class CryptAuthApiCallFlow; -// Use CryptAuthClient to make API requests to the CryptAuth service, which +// Interface for making API requests to the CryptAuth service, which // manages cryptographic credentials (ie. public keys) for a user's devices. -// CryptAuthClient only processes one request, so create a new instance for each -// request you make. DO NOT REUSE. +// Implmentations shall only processes a single request, so create a new +// instance for each request you make. DO NOT REUSE. // For documentation on each API call, see // components/proximity_auth/cryptauth/proto/cryptauth_api.proto -// Note: There is no need to set the |device_classifier| field in request -// messages. CryptAuthClient will fill this field for all requests. class CryptAuthClient { public: typedef base::Callback<void(const std::string&)> ErrorCallback; - // Creates the client using |url_request_context| to make the HTTP request. - // CryptAuthClient takes ownership of |access_token_fetcher|, which provides - // the access token authorizing CryptAuth requests. - // The |device_classifier| argument contains basic device information of the - // caller (e.g. version and device type). - CryptAuthClient( - scoped_ptr<CryptAuthAccessTokenFetcher> access_token_fetcher, - scoped_refptr<net::URLRequestContextGetter> url_request_context, - const cryptauth::DeviceClassifier& device_classifier); - virtual ~CryptAuthClient(); + virtual ~CryptAuthClient() {} // GetMyDevices typedef base::Callback<void(const cryptauth::GetMyDevicesResponse&)> GetMyDevicesCallback; - void GetMyDevices(const cryptauth::GetMyDevicesRequest& request, - const GetMyDevicesCallback& callback, - const ErrorCallback& error_callback); + virtual void GetMyDevices(const cryptauth::GetMyDevicesRequest& request, + const GetMyDevicesCallback& callback, + const ErrorCallback& error_callback) = 0; // FindEligibleUnlockDevices typedef base::Callback<void( const cryptauth::FindEligibleUnlockDevicesResponse&)> FindEligibleUnlockDevicesCallback; - void FindEligibleUnlockDevices( + virtual void FindEligibleUnlockDevices( const cryptauth::FindEligibleUnlockDevicesRequest& request, const FindEligibleUnlockDevicesCallback& callback, - const ErrorCallback& error_callback); + const ErrorCallback& error_callback) = 0; // SendDeviceSyncTickle typedef base::Callback<void(const cryptauth::SendDeviceSyncTickleResponse&)> SendDeviceSyncTickleCallback; - void SendDeviceSyncTickle( + virtual void SendDeviceSyncTickle( const cryptauth::SendDeviceSyncTickleRequest& request, const SendDeviceSyncTickleCallback& callback, - const ErrorCallback& error_callback); + const ErrorCallback& error_callback) = 0; // ToggleEasyUnlock typedef base::Callback<void(const cryptauth::ToggleEasyUnlockResponse&)> ToggleEasyUnlockCallback; - void ToggleEasyUnlock(const cryptauth::ToggleEasyUnlockRequest& request, - const ToggleEasyUnlockCallback& callback, - const ErrorCallback& error_callback); + virtual void ToggleEasyUnlock( + const cryptauth::ToggleEasyUnlockRequest& request, + const ToggleEasyUnlockCallback& callback, + const ErrorCallback& error_callback) = 0; // SetupEnrollment typedef base::Callback<void(const cryptauth::SetupEnrollmentResponse&)> SetupEnrollmentCallback; - void SetupEnrollment(const cryptauth::SetupEnrollmentRequest& request, - const SetupEnrollmentCallback& callback, - const ErrorCallback& error_callback); + virtual void SetupEnrollment(const cryptauth::SetupEnrollmentRequest& request, + const SetupEnrollmentCallback& callback, + const ErrorCallback& error_callback) = 0; // FinishEnrollment typedef base::Callback<void(const cryptauth::FinishEnrollmentResponse&)> FinishEnrollmentCallback; - void FinishEnrollment(const cryptauth::FinishEnrollmentRequest& request, - const FinishEnrollmentCallback& callback, - const ErrorCallback& error_callback); + virtual void FinishEnrollment( + const cryptauth::FinishEnrollmentRequest& request, + const FinishEnrollmentCallback& callback, + const ErrorCallback& error_callback) = 0; +}; - protected: - // Creates a CryptAuthApiCallFlow object. Exposed for testing. - virtual scoped_ptr<CryptAuthApiCallFlow> CreateFlow(const GURL& request_url); +// Interface for creating CryptAuthClient instances. Because each +// CryptAuthClient instance can only be used for one API call, a factory makes +// it easier to make multiple requests in sequence or in parallel. +class CryptAuthClientFactory { + public: + virtual ~CryptAuthClientFactory() {} - private: - // Starts a call to the API given by |request_path|, with the templated - // request and response types. The client first fetches the access token and - // then makes the HTTP request. - template <class RequestProto, class ResponseProto> - void MakeApiCall( - const std::string& request_path, - const RequestProto& request_proto, - const base::Callback<void(const ResponseProto&)>& response_callback, - const ErrorCallback& error_callback); - - // Called when the access token is obtained so the API request can be made. - template <class ResponseProto> - void OnAccessTokenFetched( - const std::string& serialized_request, - const base::Callback<void(const ResponseProto&)>& response_callback, - const std::string& access_token); - - // Called with CryptAuthApiCallFlow completes successfully to deserialize and - // return the result. - template <class ResponseProto> - void OnFlowSuccess( - const base::Callback<void(const ResponseProto&)>& result_callback, - const std::string& serialized_response); - - // Called when the current API call fails at any step. - void OnApiCallFailed(const std::string& error_message); - - // The context for network requests. - scoped_refptr<net::URLRequestContextGetter> url_request_context_; - - // Fetches the access token authorizing the API calls. - scoped_ptr<CryptAuthAccessTokenFetcher> access_token_fetcher_; - - // Contains basic device info of the client making the request that is sent to - // CryptAuth with each API call. - const cryptauth::DeviceClassifier device_classifier_; - - // Handles the current API call. - scoped_ptr<CryptAuthApiCallFlow> flow_; - - // URL path of the current request. - std::string request_path_; - - // Called when the current request fails. - ErrorCallback error_callback_; - - base::WeakPtrFactory<CryptAuthClient> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(CryptAuthClient); + virtual scoped_ptr<CryptAuthClient> CreateInstance() = 0; }; } // namespace proximity_auth -#endif // COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_CLIENT_H +#endif // COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_CLIENT_H
diff --git a/components/proximity_auth/cryptauth/cryptauth_client_factory.cc b/components/proximity_auth/cryptauth/cryptauth_client_factory.cc deleted file mode 100644 index e7d7977..0000000 --- a/components/proximity_auth/cryptauth/cryptauth_client_factory.cc +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/proximity_auth/cryptauth/cryptauth_client_factory.h" - -#include "components/proximity_auth/cryptauth/cryptauth_account_token_fetcher.h" - -namespace proximity_auth { - -CryptAuthClientFactory::CryptAuthClientFactory( - OAuth2TokenService* token_service, - const std::string& account_id, - scoped_refptr<net::URLRequestContextGetter> url_request_context, - const cryptauth::DeviceClassifier& device_classifier) - : token_service_(token_service), - account_id_(account_id), - url_request_context_(url_request_context), - device_classifier_(device_classifier) { -} - -CryptAuthClientFactory::~CryptAuthClientFactory() { -} - -scoped_ptr<CryptAuthClient> CryptAuthClientFactory::CreateInstance() { - scoped_ptr<CryptAuthAccessTokenFetcher> access_token_fetcher( - new CryptAuthAccountTokenFetcher(token_service_, account_id_)); - return make_scoped_ptr(new CryptAuthClient( - access_token_fetcher.Pass(), url_request_context_, device_classifier_)); -} - -} // namespace proximity_auth
diff --git a/components/proximity_auth/cryptauth/cryptauth_client_factory.h b/components/proximity_auth/cryptauth/cryptauth_client_factory.h deleted file mode 100644 index c1dc95ba..0000000 --- a/components/proximity_auth/cryptauth/cryptauth_client_factory.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_CLIENT_FACTORY_H -#define COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_CLIENT_FACTORY_H - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "components/proximity_auth/cryptauth/cryptauth_client.h" -#include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" -#include "google_apis/gaia/oauth2_token_service.h" -#include "net/url_request/url_request_context_getter.h" - -namespace proximity_auth { - -class CryptAuthClient; - -// Factory for creating CryptAuthClient instances. Because each CryptAuthClient -// instance can only be used for one API call, this class helps making multiple -// requests in sequence or parallel easier. -class CryptAuthClientFactory { - public: - // Creates the factory. - // |token_service|: Gets the user's access token. - // Needs to outlive this object. - // |account_id|: The account id of the user. - // |url_request_context|: The request context to make the HTTP requests. - // |device_classifier|: Contains basic device information of the client. - CryptAuthClientFactory( - OAuth2TokenService* token_service, - const std::string& account_id, - scoped_refptr<net::URLRequestContextGetter> url_request_context, - const cryptauth::DeviceClassifier& device_classifier); - virtual ~CryptAuthClientFactory(); - - // Creates and returns a CryptAuthClient instance that is owned by the caller. - scoped_ptr<CryptAuthClient> CreateInstance(); - - private: - OAuth2TokenService* token_service_; - const std::string account_id_; - const scoped_refptr<net::URLRequestContextGetter> url_request_context_; - const cryptauth::DeviceClassifier device_classifier_; - - DISALLOW_COPY_AND_ASSIGN(CryptAuthClientFactory); -}; - -} // namespace proximity_auth - -#endif // COMPONENTS_PROXIMITY_AUTH_CRYPT_AUTH_CLIENT_FACTORY_H
diff --git a/components/proximity_auth/cryptauth/cryptauth_client.cc b/components/proximity_auth/cryptauth/cryptauth_client_impl.cc similarity index 70% rename from components/proximity_auth/cryptauth/cryptauth_client.cc rename to components/proximity_auth/cryptauth/cryptauth_client_impl.cc index 7ad14e2..32ec7041 100644 --- a/components/proximity_auth/cryptauth/cryptauth_client.cc +++ b/components/proximity_auth/cryptauth/cryptauth_client_impl.cc
@@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/proximity_auth/cryptauth/cryptauth_client_impl.h" + #include "base/bind.h" #include "base/command_line.h" -#include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" -#include "components/proximity_auth/cryptauth/cryptauth_api_call_flow.h" -#include "components/proximity_auth/cryptauth/cryptauth_client.h" -#include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" +#include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher_impl.h" #include "components/proximity_auth/switches.h" -#include "net/url_request/url_request_context_getter.h" namespace proximity_auth { @@ -47,27 +45,30 @@ } // namespace -CryptAuthClient::CryptAuthClient( +CryptAuthClientImpl::CryptAuthClientImpl( + scoped_ptr<CryptAuthApiCallFlow> api_call_flow, scoped_ptr<CryptAuthAccessTokenFetcher> access_token_fetcher, scoped_refptr<net::URLRequestContextGetter> url_request_context, const cryptauth::DeviceClassifier& device_classifier) - : url_request_context_(url_request_context), + : api_call_flow_(api_call_flow.Pass()), access_token_fetcher_(access_token_fetcher.Pass()), + url_request_context_(url_request_context), device_classifier_(device_classifier), + has_call_started_(false), weak_ptr_factory_(this) { } -CryptAuthClient::~CryptAuthClient() { +CryptAuthClientImpl::~CryptAuthClientImpl() { } -void CryptAuthClient::GetMyDevices( +void CryptAuthClientImpl::GetMyDevices( const cryptauth::GetMyDevicesRequest& request, const GetMyDevicesCallback& callback, const ErrorCallback& error_callback) { MakeApiCall(kGetMyDevicesPath, request, callback, error_callback); } -void CryptAuthClient::FindEligibleUnlockDevices( +void CryptAuthClientImpl::FindEligibleUnlockDevices( const cryptauth::FindEligibleUnlockDevicesRequest& request, const FindEligibleUnlockDevicesCallback& callback, const ErrorCallback& error_callback) { @@ -75,50 +76,46 @@ error_callback); } -void CryptAuthClient::SendDeviceSyncTickle( +void CryptAuthClientImpl::SendDeviceSyncTickle( const cryptauth::SendDeviceSyncTickleRequest& request, const SendDeviceSyncTickleCallback& callback, const ErrorCallback& error_callback) { MakeApiCall(kSendDeviceSyncTicklePath, request, callback, error_callback); } -void CryptAuthClient::ToggleEasyUnlock( +void CryptAuthClientImpl::ToggleEasyUnlock( const cryptauth::ToggleEasyUnlockRequest& request, const ToggleEasyUnlockCallback& callback, const ErrorCallback& error_callback) { MakeApiCall(kToggleEasyUnlockPath, request, callback, error_callback); } -void CryptAuthClient::SetupEnrollment( +void CryptAuthClientImpl::SetupEnrollment( const cryptauth::SetupEnrollmentRequest& request, const SetupEnrollmentCallback& callback, const ErrorCallback& error_callback) { MakeApiCall(kSetupEnrollmentPath, request, callback, error_callback); } -void CryptAuthClient::FinishEnrollment( +void CryptAuthClientImpl::FinishEnrollment( const cryptauth::FinishEnrollmentRequest& request, const FinishEnrollmentCallback& callback, const ErrorCallback& error_callback) { MakeApiCall(kFinishEnrollmentPath, request, callback, error_callback); } -scoped_ptr<CryptAuthApiCallFlow> CryptAuthClient::CreateFlow( - const GURL& request_url) { - return make_scoped_ptr(new CryptAuthApiCallFlow(request_url)); -} - template <class RequestProto, class ResponseProto> -void CryptAuthClient::MakeApiCall( +void CryptAuthClientImpl::MakeApiCall( const std::string& request_path, const RequestProto& request_proto, const base::Callback<void(const ResponseProto&)>& response_callback, const ErrorCallback& error_callback) { - if (flow_) { + if (has_call_started_) { error_callback.Run( "Client has been used for another request. Do not reuse."); return; } + has_call_started_ = true; // The |device_classifier| field must be present for all CryptAuth requests. RequestProto request_copy(request_proto); @@ -134,12 +131,12 @@ request_path_ = request_path; error_callback_ = error_callback; access_token_fetcher_->FetchAccessToken(base::Bind( - &CryptAuthClient::OnAccessTokenFetched<ResponseProto>, + &CryptAuthClientImpl::OnAccessTokenFetched<ResponseProto>, weak_ptr_factory_.GetWeakPtr(), serialized_request, response_callback)); } template <class ResponseProto> -void CryptAuthClient::OnAccessTokenFetched( +void CryptAuthClientImpl::OnAccessTokenFetched( const std::string& serialized_request, const base::Callback<void(const ResponseProto&)>& response_callback, const std::string& access_token) { @@ -148,16 +145,17 @@ return; } - flow_ = CreateFlow(CreateRequestUrl(request_path_)); - flow_->Start(url_request_context_.get(), access_token, serialized_request, - base::Bind(&CryptAuthClient::OnFlowSuccess<ResponseProto>, - weak_ptr_factory_.GetWeakPtr(), response_callback), - base::Bind(&CryptAuthClient::OnApiCallFailed, - weak_ptr_factory_.GetWeakPtr())); + api_call_flow_->Start( + CreateRequestUrl(request_path_), url_request_context_.get(), access_token, + serialized_request, + base::Bind(&CryptAuthClientImpl::OnFlowSuccess<ResponseProto>, + weak_ptr_factory_.GetWeakPtr(), response_callback), + base::Bind(&CryptAuthClientImpl::OnApiCallFailed, + weak_ptr_factory_.GetWeakPtr())); } template <class ResponseProto> -void CryptAuthClient::OnFlowSuccess( +void CryptAuthClientImpl::OnFlowSuccess( const base::Callback<void(const ResponseProto&)>& result_callback, const std::string& serialized_response) { ResponseProto response; @@ -168,8 +166,31 @@ result_callback.Run(response); }; -void CryptAuthClient::OnApiCallFailed(const std::string& error_message) { +void CryptAuthClientImpl::OnApiCallFailed(const std::string& error_message) { error_callback_.Run(error_message); } +// CryptAuthClientFactoryImpl +CryptAuthClientFactoryImpl::CryptAuthClientFactoryImpl( + OAuth2TokenService* token_service, + const std::string& account_id, + scoped_refptr<net::URLRequestContextGetter> url_request_context, + const cryptauth::DeviceClassifier& device_classifier) + : token_service_(token_service), + account_id_(account_id), + url_request_context_(url_request_context), + device_classifier_(device_classifier) { +} + +CryptAuthClientFactoryImpl::~CryptAuthClientFactoryImpl() { +} + +scoped_ptr<CryptAuthClient> CryptAuthClientFactoryImpl::CreateInstance() { + return make_scoped_ptr(new CryptAuthClientImpl( + make_scoped_ptr(new CryptAuthApiCallFlow()), + make_scoped_ptr( + new CryptAuthAccessTokenFetcherImpl(token_service_, account_id_)), + url_request_context_, device_classifier_)); +} + } // proximity_auth
diff --git a/components/proximity_auth/cryptauth/cryptauth_client_impl.h b/components/proximity_auth/cryptauth/cryptauth_client_impl.h new file mode 100644 index 0000000..aa19594b --- /dev/null +++ b/components/proximity_auth/cryptauth/cryptauth_client_impl.h
@@ -0,0 +1,144 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_CLIENT_IMPL_H +#define COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_CLIENT_IMPL_H + +#include "base/memory/weak_ptr.h" +#include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" +#include "components/proximity_auth/cryptauth/cryptauth_api_call_flow.h" +#include "components/proximity_auth/cryptauth/cryptauth_client.h" +#include "net/url_request/url_request_context_getter.h" + +class OAuth2TokenService; + +namespace proximity_auth { + +// Implementation of CryptAuthClient. +// Note: There is no need to set the |device_classifier| field in request +// messages. CryptAuthClient will fill this field for all requests. +class CryptAuthClientImpl : public CryptAuthClient { + public: + typedef base::Callback<void(const std::string&)> ErrorCallback; + + // Creates the client using |url_request_context| to make the HTTP request + // through |api_call_flow|. CryptAuthClientImpl takes ownership of + // |access_token_fetcher|, which provides the access token authorizing + // CryptAuth requests. The |device_classifier| argument contains basic device + // information of the caller (e.g. version and device type). + CryptAuthClientImpl( + scoped_ptr<CryptAuthApiCallFlow> api_call_flow, + scoped_ptr<CryptAuthAccessTokenFetcher> access_token_fetcher, + scoped_refptr<net::URLRequestContextGetter> url_request_context, + const cryptauth::DeviceClassifier& device_classifier); + ~CryptAuthClientImpl() override; + + // CryptAuthClient: + void GetMyDevices(const cryptauth::GetMyDevicesRequest& request, + const GetMyDevicesCallback& callback, + const ErrorCallback& error_callback) override; + void FindEligibleUnlockDevices( + const cryptauth::FindEligibleUnlockDevicesRequest& request, + const FindEligibleUnlockDevicesCallback& callback, + const ErrorCallback& error_callback) override; + void SendDeviceSyncTickle( + const cryptauth::SendDeviceSyncTickleRequest& request, + const SendDeviceSyncTickleCallback& callback, + const ErrorCallback& error_callback) override; + void ToggleEasyUnlock(const cryptauth::ToggleEasyUnlockRequest& request, + const ToggleEasyUnlockCallback& callback, + const ErrorCallback& error_callback) override; + void SetupEnrollment(const cryptauth::SetupEnrollmentRequest& request, + const SetupEnrollmentCallback& callback, + const ErrorCallback& error_callback) override; + void FinishEnrollment(const cryptauth::FinishEnrollmentRequest& request, + const FinishEnrollmentCallback& callback, + const ErrorCallback& error_callback) override; + + private: + // Starts a call to the API given by |request_path|, with the templated + // request and response types. The client first fetches the access token and + // then makes the HTTP request. + template <class RequestProto, class ResponseProto> + void MakeApiCall( + const std::string& request_path, + const RequestProto& request_proto, + const base::Callback<void(const ResponseProto&)>& response_callback, + const ErrorCallback& error_callback); + + // Called when the access token is obtained so the API request can be made. + template <class ResponseProto> + void OnAccessTokenFetched( + const std::string& serialized_request, + const base::Callback<void(const ResponseProto&)>& response_callback, + const std::string& access_token); + + // Called with CryptAuthApiCallFlow completes successfully to deserialize and + // return the result. + template <class ResponseProto> + void OnFlowSuccess( + const base::Callback<void(const ResponseProto&)>& result_callback, + const std::string& serialized_response); + + // Called when the current API call fails at any step. + void OnApiCallFailed(const std::string& error_message); + + // Constructs and executes the actual HTTP request. + scoped_ptr<CryptAuthApiCallFlow> api_call_flow_; + + // Fetches the access token authorizing the API calls. + scoped_ptr<CryptAuthAccessTokenFetcher> access_token_fetcher_; + + // The context for network requests. + scoped_refptr<net::URLRequestContextGetter> url_request_context_; + + // Contains basic device info of the client making the request that is sent to + // CryptAuth with each API call. + const cryptauth::DeviceClassifier device_classifier_; + + // True if an API call has been started. Remains true even after the API call + // completes. + bool has_call_started_; + + // URL path of the current request. + std::string request_path_; + + // Called when the current request fails. + ErrorCallback error_callback_; + + base::WeakPtrFactory<CryptAuthClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CryptAuthClientImpl); +}; + +// Implementation of CryptAuthClientFactory. +class CryptAuthClientFactoryImpl : public CryptAuthClientFactory { + public: + // |token_service|: Gets the user's access token. + // Not owned, so |token_service| needs to outlive this object. + // |account_id|: The account id of the user. + // |url_request_context|: The request context to make the HTTP requests. + // |device_classifier|: Contains basic device information of the client. + CryptAuthClientFactoryImpl( + OAuth2TokenService* token_service, + const std::string& account_id, + scoped_refptr<net::URLRequestContextGetter> url_request_context, + const cryptauth::DeviceClassifier& device_classifier); + ~CryptAuthClientFactoryImpl() override; + + // CryptAuthClientFactory: + scoped_ptr<CryptAuthClient> CreateInstance() override; + + private: + OAuth2TokenService* token_service_; + const std::string account_id_; + const scoped_refptr<net::URLRequestContextGetter> url_request_context_; + const cryptauth::DeviceClassifier device_classifier_; + + DISALLOW_COPY_AND_ASSIGN(CryptAuthClientFactoryImpl); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_CRYPTAUTH_CLIENT_IMPL_H
diff --git a/components/proximity_auth/cryptauth/cryptauth_client_unittest.cc b/components/proximity_auth/cryptauth/cryptauth_client_impl_unittest.cc similarity index 90% rename from components/proximity_auth/cryptauth/cryptauth_client_unittest.cc rename to components/proximity_auth/cryptauth/cryptauth_client_impl_unittest.cc index 61d4d46..57ccb531 100644 --- a/components/proximity_auth/cryptauth/cryptauth_client_unittest.cc +++ b/components/proximity_auth/cryptauth/cryptauth_client_impl_unittest.cc
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/proximity_auth/cryptauth/cryptauth_client.h" +#include "components/proximity_auth/cryptauth/cryptauth_client_impl.h" #include "base/command_line.h" #include "base/test/null_task_runner.h" #include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" #include "components/proximity_auth/cryptauth/cryptauth_api_call_flow.h" -#include "components/proximity_auth/cryptauth/cryptauth_client_factory.h" #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" #include "components/proximity_auth/switches.h" #include "google_apis/gaia/fake_oauth2_token_service.h" @@ -16,6 +15,7 @@ #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" using testing::_; using testing::DoAll; @@ -61,11 +61,12 @@ // Mock CryptAuthApiCallFlow, which handles the HTTP requests to CryptAuth. class MockCryptAuthApiCallFlow : public CryptAuthApiCallFlow { public: - MockCryptAuthApiCallFlow() : CryptAuthApiCallFlow(GURL(std::string())) {} + MockCryptAuthApiCallFlow() : CryptAuthApiCallFlow() {} virtual ~MockCryptAuthApiCallFlow() {} - MOCK_METHOD5(Start, - void(net::URLRequestContextGetter* context, + MOCK_METHOD6(Start, + void(const GURL&, + net::URLRequestContextGetter* context, const std::string& access_token, const std::string& serialized_request, const ResultCallback& result_callback, @@ -75,32 +76,6 @@ DISALLOW_COPY_AND_ASSIGN(MockCryptAuthApiCallFlow); }; -// Subclass of CryptAuthClient to use as test harness. -class MockCryptAuthClient : public CryptAuthClient { - public: - // Ownership of |access_token_fetcher| is passed to the superclass. Due to the - // limitations of gmock, we need to use a raw pointer argument rather than a - // scoped_ptr. - MockCryptAuthClient( - CryptAuthAccessTokenFetcher* access_token_fetcher, - scoped_refptr<net::URLRequestContextGetter> url_request_context, - const cryptauth::DeviceClassifier& device_classifier) - : CryptAuthClient(make_scoped_ptr(access_token_fetcher), - url_request_context, - device_classifier) {} - virtual ~MockCryptAuthClient() {} - - MOCK_METHOD1(CreateFlowProxy, CryptAuthApiCallFlow*(const GURL& request_url)); - - scoped_ptr<CryptAuthApiCallFlow> CreateFlow( - const GURL& request_url) override { - return make_scoped_ptr(CreateFlowProxy(request_url)); - }; - - private: - DISALLOW_COPY_AND_ASSIGN(MockCryptAuthClient); -}; - // Callback that should never be invoked. template <class T> void NotCalled(const T& type) { @@ -119,6 +94,7 @@ protected: ProximityAuthCryptAuthClientTest() : access_token_fetcher_(new FakeCryptAuthAccessTokenFetcher()), + api_call_flow_(new StrictMock<MockCryptAuthApiCallFlow>()), url_request_context_( new net::TestURLRequestContextGetter(new base::NullTaskRunner())), serialized_request_(std::string()) {} @@ -134,24 +110,20 @@ device_classifier.set_device_software_package(kDeviceSoftwarePackage); device_classifier.set_device_type(kDeviceType); - client_.reset(new StrictMock<MockCryptAuthClient>( - access_token_fetcher_, url_request_context_, device_classifier)); + client_.reset(new CryptAuthClientImpl( + make_scoped_ptr(api_call_flow_), make_scoped_ptr(access_token_fetcher_), + url_request_context_, device_classifier)); } // Sets up an expectation and captures a CryptAuth API request to // |request_url|. void ExpectRequest(const std::string& request_url) { - StrictMock<MockCryptAuthApiCallFlow>* api_call_flow = - new StrictMock<MockCryptAuthApiCallFlow>(); - - EXPECT_CALL(*client_, CreateFlowProxy(GURL(request_url))) - .WillOnce(Return(api_call_flow)); - - EXPECT_CALL(*api_call_flow, - Start(url_request_context_.get(), kAccessToken, _, _, _)) - .WillOnce(DoAll(SaveArg<2>(&serialized_request_), - SaveArg<3>(&flow_result_callback_), - SaveArg<4>(&flow_error_callback_))); + GURL url(request_url); + EXPECT_CALL(*api_call_flow_, + Start(url, url_request_context_.get(), kAccessToken, _, _, _)) + .WillOnce(DoAll(SaveArg<3>(&serialized_request_), + SaveArg<4>(&flow_result_callback_), + SaveArg<5>(&flow_error_callback_))); } // Returns |response_proto| as the result to the current API request. @@ -169,9 +141,11 @@ protected: // Owned by |client_|. FakeCryptAuthAccessTokenFetcher* access_token_fetcher_; + // Owned by |client_|. + StrictMock<MockCryptAuthApiCallFlow>* api_call_flow_; scoped_refptr<net::URLRequestContextGetter> url_request_context_; - scoped_ptr<StrictMock<MockCryptAuthClient>> client_; + scoped_ptr<CryptAuthClient> client_; std::string serialized_request_; CryptAuthApiCallFlow::ResultCallback flow_result_callback_;
diff --git a/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc b/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc index f9aafcb..476721c 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enrollment_utils.cc
@@ -5,7 +5,7 @@ #include "components/proximity_auth/cryptauth/cryptauth_enrollment_utils.h" #include "base/sha1.h" -#include "components/proximity_auth/base64url.h" +#include "components/proximity_auth/cryptauth/base64url.h" namespace proximity_auth {
diff --git a/components/proximity_auth/wire_message.cc b/components/proximity_auth/wire_message.cc index 5b64da9..3e0c364 100644 --- a/components/proximity_auth/wire_message.cc +++ b/components/proximity_auth/wire_message.cc
@@ -8,7 +8,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/values.h" -#include "components/proximity_auth/base64url.h" +#include "components/proximity_auth/cryptauth/base64url.h" // The wire messages have a simple format: // [ message version ] [ body length ] [ JSON body ]
diff --git a/components/sessions/BUILD.gn b/components/sessions/BUILD.gn index d66b8674..6d8c4a6 100644 --- a/components/sessions/BUILD.gn +++ b/components/sessions/BUILD.gn
@@ -38,6 +38,7 @@ "//base", "//skia", "//sync", + "//sync/protocol", "//third_party/protobuf:protobuf_lite", "//ui/base", "//ui/gfx",
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index 28f4c88c..36ba75a9 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -4,6 +4,7 @@ #include "components/signin/core/browser/gaia_cookie_manager_service.h" +#include <queue> #include <vector> #include "base/json/json_reader.h" @@ -22,7 +23,6 @@ #include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher_delegate.h" - namespace { // In case of an error while fetching using the GaiaAuthFetcher, retry with @@ -61,8 +61,56 @@ error.state() == GoogleServiceAuthError::REQUEST_CANCELED; } +enum GaiaCookieRequestType { + ADD_ACCOUNT, + LOG_OUT_ALL_ACCOUNTS, + LOG_OUT_ONE_ACCOUNT, + LIST_ACCOUNTS +}; + } // namespace +GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest( + GaiaCookieRequestType request_type, + const std::string& account_id, + const GaiaCookieManagerService::ListAccountsCallback& + list_accounts_callback) + : request_type_(request_type), + account_id_(account_id), + list_accounts_callback_(list_accounts_callback) {} + +GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() { +} + +// static +GaiaCookieManagerService::GaiaCookieRequest +GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest( + const std::string& account_id) { + return GaiaCookieManagerService::GaiaCookieRequest( + GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT, + account_id, + GaiaCookieManagerService::ListAccountsCallback()); +} + +// static +GaiaCookieManagerService::GaiaCookieRequest +GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest() { + return GaiaCookieManagerService::GaiaCookieRequest( + GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT, + std::string(), + GaiaCookieManagerService::ListAccountsCallback()); +} + +GaiaCookieManagerService::GaiaCookieRequest +GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest( + const GaiaCookieManagerService::ListAccountsCallback& + list_accounts_callback) { + return GaiaCookieManagerService::GaiaCookieRequest( + GaiaCookieManagerService::GaiaCookieRequestType::LIST_ACCOUNTS, + std::string(), + list_accounts_callback); +} + GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher( GaiaCookieManagerService* helper) : helper_(helper) { @@ -235,16 +283,82 @@ GaiaCookieManagerService::~GaiaCookieManagerService() { CancelAll(); - DCHECK(accounts_.empty()); + DCHECK(requests_.empty()); } void GaiaCookieManagerService::AddAccountToCookie( const std::string& account_id) { DCHECK(!account_id.empty()); VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id; - accounts_.push_back(account_id); - if (accounts_.size() == 1) - StartFetching(); + requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest(account_id)); + if (requests_.size() == 1) + StartFetchingUbertoken(); +} + +void GaiaCookieManagerService::ListAccounts( + const ListAccountsCallback& callback) { + // Not implemented yet. + NOTREACHED(); + + // TODO(mlerman): Once this service listens to all GAIA cookie changes, cache + // the results of ListAccounts, and return them here if the GAIA cookie + // hasn't changed since the last call. + + // If there's a GAIA call being executed, wait for it to complete. If it was + // another /ListAccounts then we'll use the results it caches. + if (gaia_auth_fetcher_) + return; + + VLOG(1) << "GaiaCookieManagerService::ListAccounts"; + gaia_auth_fetcher_.reset( + new GaiaAuthFetcher(this, source_, + signin_client_->GetURLRequestContext())); + gaia_auth_fetcher_->StartListAccounts(); +} + +void GaiaCookieManagerService::LogOutAllAccounts() { + VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts"; + + bool log_out_queued = false; + if (!requests_.empty()) { + // Track requests to keep; all other unstarted requests will be removed. + std::vector<GaiaCookieRequest> requests_to_keep; + + // Check all pending, non-executing requests. + for (auto it = requests_.begin() + 1; it != requests_.end(); ++it) { + if (it->request_type() == GaiaCookieRequestType::ADD_ACCOUNT) { + // We have a pending log in request for an account followed by + // a signout. + GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); + SignalComplete(it->account_id(), error); + } + + // Keep all requests except for ADD_ACCOUNTS. + if (it->request_type() != GaiaCookieRequestType::ADD_ACCOUNT) + requests_to_keep.push_back(*it); + + // Verify a LOG_OUT isn't already queued. + if (it->request_type() == GaiaCookieRequestType::LOG_OUT) + log_out_queued = true; + } + + // Verify a LOG_OUT isn't currently being processed. + if (requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT) + log_out_queued = true; + + // Remove all but the executing request. Re-add all requests being kept. + if (requests_.size() > 1) { + requests_.erase(requests_.begin() + 1, requests_.end()); + requests_.insert( + requests_.end(), requests_to_keep.begin(), requests_to_keep.end()); + } + } + + if (!log_out_queued) { + requests_.push_back(GaiaCookieRequest::CreateLogOutRequest()); + if (requests_.size() == 1) + StartLogOutUrlFetch(); + } } void GaiaCookieManagerService::AddObserver(Observer* observer) { @@ -259,63 +373,10 @@ VLOG(1) << "GaiaCookieManagerService::CancelAll"; gaia_auth_fetcher_.reset(); uber_token_fetcher_.reset(); - accounts_.clear(); + requests_.clear(); gaia_auth_fetcher_timer_.Stop(); } -void GaiaCookieManagerService::LogOut( - const std::string& account_id, - const std::vector<std::string>& accounts) { - DCHECK(!account_id.empty()); - VLOG(1) << "GaiaCookieManagerService::LogOut: " << account_id - << " accounts=" << accounts.size(); - LogOutInternal(account_id, accounts); -} - -void GaiaCookieManagerService::LogOutInternal( - const std::string& account_id, - const std::vector<std::string>& accounts) { - bool pending = !accounts_.empty(); - - if (pending) { - for (std::deque<std::string>::const_iterator it = accounts_.begin() + 1; - it != accounts_.end(); it++) { - if (!it->empty() && - (std::find(accounts.begin(), accounts.end(), *it) == accounts.end() || - *it == account_id)) { - // We have a pending log in request for an account followed by - // a signout. - GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); - SignalComplete(*it, error); - } - } - - // Remove every thing in the work list besides the one that is running. - accounts_.resize(1); - } - - // Signal a logout to be the next thing to do unless the pending - // action is already a logout. - if (!pending || !accounts_.front().empty()) - accounts_.push_back(""); - - for (std::vector<std::string>::const_iterator it = accounts.begin(); - it != accounts.end(); it++) { - if (*it != account_id) { - DCHECK(!it->empty()); - accounts_.push_back(*it); - } - } - - if (!pending) - StartLogOutUrlFetch(); -} - -void GaiaCookieManagerService::LogOutAllAccounts() { - VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts"; - LogOutInternal("", std::vector<std::string>()); -} - void GaiaCookieManagerService::SignalComplete( const std::string& account_id, const GoogleServiceAuthError& error) { @@ -332,7 +393,7 @@ } void GaiaCookieManagerService::StartLogOutUrlFetch() { - DCHECK(accounts_.front().empty()); + DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); VLOG(1) << "GaiaCookieManagerService::StartLogOutUrlFetch"; GURL logout_url(GaiaUrls::GetInstance()->service_logout_url().Resolve( base::StringPrintf("?source=%s", source_.c_str()))); @@ -345,7 +406,7 @@ void GaiaCookieManagerService::OnUbertokenSuccess( const std::string& uber_token) { VLOG(1) << "GaiaCookieManagerService::OnUbertokenSuccess" - << " account=" << accounts_.front(); + << " account=" << requests_.front().account_id(); gaia_auth_fetcher_retries_ = 0; uber_token_ = uber_token; StartFetchingMergeSession(); @@ -354,16 +415,18 @@ void GaiaCookieManagerService::OnUbertokenFailure( const GoogleServiceAuthError& error) { VLOG(1) << "Failed to retrieve ubertoken" - << " account=" << accounts_.front() << " error=" << error.ToString(); - const std::string account_id = accounts_.front(); - HandleNextAccount(); + << " account=" << requests_.front().account_id() + << " error=" << error.ToString(); + const std::string account_id = requests_.front().account_id(); + HandleNextRequest(); SignalComplete(account_id, error); } void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) { - VLOG(1) << "MergeSession successful account=" << accounts_.front(); - const std::string account_id = accounts_.front(); - HandleNextAccount(); + VLOG(1) << "MergeSession successful account=" + << requests_.front().account_id(); + const std::string account_id = requests_.front().account_id(); + HandleNextRequest(); SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone()); gaia_auth_fetcher_backoff_.InformOfRequest(true); @@ -373,8 +436,8 @@ void GaiaCookieManagerService::OnMergeSessionFailure( const GoogleServiceAuthError& error) { VLOG(1) << "Failed MergeSession" - << " account=" << accounts_.front() << " error=" << error.ToString() - << " on retry=" << gaia_auth_fetcher_retries_; + << " account=" << requests_.front().account_id() + << " error=" << error.ToString(); if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries && IsTransientError(error)) { @@ -386,18 +449,18 @@ } uber_token_ = std::string(); - const std::string account_id = accounts_.front(); - HandleNextAccount(); + const std::string account_id = requests_.front().account_id(); + HandleNextRequest(); SignalComplete(account_id, error); } -void GaiaCookieManagerService::StartFetching() { +void GaiaCookieManagerService::StartFetchingUbertoken() { VLOG(1) << "GaiaCookieManagerService::StartFetching account_id=" - << accounts_.front(); + << requests_.front().account_id(); uber_token_fetcher_.reset( new UbertokenFetcher(token_service_, this, source_, signin_client_->GetURLRequestContext())); - uber_token_fetcher_->StartFetchingToken(accounts_.front()); + uber_token_fetcher_->StartFetchingToken(requests_.front().account_id()); } void GaiaCookieManagerService::StartFetchingMergeSession() { @@ -414,23 +477,28 @@ void GaiaCookieManagerService::OnURLFetchComplete( const net::URLFetcher* source) { - DCHECK(accounts_.front().empty()); + DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); VLOG(1) << "GaiaCookieManagerService::OnURLFetchComplete"; - HandleNextAccount(); + HandleNextRequest(); } -void GaiaCookieManagerService::HandleNextAccount() { - VLOG(1) << "GaiaCookieManagerService::HandleNextAccount"; - accounts_.pop_front(); +void GaiaCookieManagerService::HandleNextRequest() { + VLOG(1) << "GaiaCookieManagerService::HandleNextRequest"; + requests_.pop_front(); gaia_auth_fetcher_.reset(); - if (accounts_.empty()) { - VLOG(1) << "GaiaCookieManagerService::HandleNextAccount: no more"; + if (requests_.empty()) { + VLOG(1) << "GaiaCookieManagerService::HandleNextRequest: no more"; uber_token_fetcher_.reset(); } else { - if (accounts_.front().empty()) { - StartLogOutUrlFetch(); - } else { - StartFetching(); - } + switch (requests_.front().request_type()) { + case GaiaCookieRequestType::ADD_ACCOUNT: + StartFetchingUbertoken(); + break; + case GaiaCookieRequestType::LOG_OUT: + StartLogOutUrlFetch(); + break; + case GaiaCookieRequestType::LIST_ACCOUNTS: + break; + }; } }
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h index 6eef9db..c288f448 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.h +++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -36,6 +36,48 @@ public UbertokenConsumer, public net::URLFetcherDelegate { public: + typedef base::Callback<void(const std::string& data, + const GoogleServiceAuthError& error)> + ListAccountsCallback; + + + enum GaiaCookieRequestType { + ADD_ACCOUNT, + LOG_OUT, + LIST_ACCOUNTS + }; + + // Contains the information and parameters for any request. + class GaiaCookieRequest { + public: + ~GaiaCookieRequest(); + + GaiaCookieRequestType request_type() const { return request_type_; } + const std::string& account_id() const {return account_id_; } + const GaiaCookieManagerService::ListAccountsCallback& + list_accounts_callback() const { + return list_accounts_callback_; + } + + static GaiaCookieRequest CreateAddAccountRequest( + const std::string& account_id); + static GaiaCookieRequest CreateLogOutRequest(); + static GaiaCookieRequest CreateListAccountsRequest( + const GaiaCookieManagerService::ListAccountsCallback& + list_accounts_callback); + + private: + GaiaCookieRequest( + GaiaCookieRequestType request_type, + const std::string& account_id, + const GaiaCookieManagerService::ListAccountsCallback& + list_accounts_callback); + + GaiaCookieRequestType request_type_; + std::string account_id_; + GaiaCookieManagerService::ListAccountsCallback list_accounts_callback_; + }; + class Observer { public: // Called whenever a merge session is completed. The account that was @@ -124,6 +166,8 @@ void AddAccountToCookie(const std::string& account_id); + void ListAccounts(const ListAccountsCallback& callback); + // Add or remove observers of this helper. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -131,13 +175,6 @@ // Cancel all login requests. void CancelAll(); - // Signout of |account_id| given a list of accounts already signed in. - // Since this involves signing out of all accounts and resigning back in, - // the order which |accounts| are given is important as it will dictate - // the sign in order. |account_id| does not have to be in |accounts|. - void LogOut(const std::string& account_id, - const std::vector<std::string>& accounts); - // Signout all accounts. void LogOutAllAccounts(); @@ -148,7 +185,7 @@ const GoogleServiceAuthError& error); // Returns true of there are pending log ins or outs. - bool is_running() const { return accounts_.size() > 0; } + bool is_running() const { return requests_.size() > 0; } // Start the process of fetching the external check connection result so that // its ready when we try to perform a merge session. @@ -167,12 +204,9 @@ void OnMergeSessionSuccess(const std::string& data) override; void OnMergeSessionFailure(const GoogleServiceAuthError& error) override; - void LogOutInternal(const std::string& account_id, - const std::vector<std::string>& accounts); - - // Starts the process of fetching the uber token and then performing a merge - // session for the next account. Virtual so that it can be overriden in tests. - virtual void StartFetching(); + // Starts the proess of fetching the uber token and performing a merge session + // for the next account. Virtual so that it can be overriden in tests. + virtual void StartFetchingUbertoken(); // Virtual for testing purposes. virtual void StartFetchingMergeSession(); @@ -180,8 +214,8 @@ // Virtual for testing purpose. virtual void StartLogOutUrlFetch(); - // Start the next merge session, if needed. - void HandleNextAccount(); + // Start the next request, if needed. + void HandleNextRequest(); // Overridden from URLFetcherDelgate. void OnURLFetchComplete(const net::URLFetcher* source) override; @@ -200,10 +234,10 @@ // The last fetched ubertoken, for use in MergeSession retries. std::string uber_token_; - // A worklist for this class. Accounts names are stored here if - // we are pending a signin action for that account. Empty strings - // represent a signout request. - std::deque<std::string> accounts_; + // A worklist for this class. Stores any pending requests that couldn't be + // executed right away, since this class only permits one request to be + // executed at a time. + std::deque<GaiaCookieRequest> requests_; // List of observers to notify when merge session completes. // Makes sure list is empty on destruction.
diff --git a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc index c32ea37..9b584b0 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -58,7 +58,7 @@ virtual ~InstrumentedGaiaCookieManagerService() { total--; } - MOCK_METHOD0(StartFetching, void()); + MOCK_METHOD0(StartFetchingUbertoken, void()); MOCK_METHOD0(StartFetchingMergeSession, void()); MOCK_METHOD0(StartLogOutUrlFetch, void()); @@ -137,7 +137,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()); + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); @@ -149,7 +149,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()); + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", error())); @@ -163,7 +163,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()); + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(helper, StartFetchingMergeSession()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); @@ -185,7 +185,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()); + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(helper, StartFetchingMergeSession()).Times(2); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); @@ -215,7 +215,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()); + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", error())); @@ -227,7 +227,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()).Times(2); + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", @@ -243,7 +243,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()).Times(2); + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", error())); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", @@ -259,7 +259,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()).Times(2); + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", error())); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", @@ -275,7 +275,7 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - EXPECT_CALL(helper, StartFetching()).Times(4); + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(4); EXPECT_CALL(observer, OnAddAccountToCookieCompleted(_, no_error())).Times(4); helper.AddAccountToCookie("acc1@gmail.com"); @@ -293,36 +293,127 @@ SimulateMergeSessionSuccess(&helper, "token4"); } -TEST_F(GaiaCookieManagerServiceTest, LogOut) { +TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsNoQueue) { InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - std::vector<std::string> current_accounts; - current_accounts.push_back("acc1@gmail.com"); - current_accounts.push_back("acc2@gmail.com"); - current_accounts.push_back("acc3@gmail.com"); - + EXPECT_CALL(helper, StartFetchingUbertoken()); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", + no_error())); EXPECT_CALL(helper, StartLogOutUrlFetch()); - EXPECT_CALL(helper, StartFetching()).Times(2); + + helper.AddAccountToCookie("acc2@gmail.com"); + SimulateMergeSessionSuccess(&helper, "token1"); + + helper.LogOutAllAccounts(); + SimulateLogoutSuccess(&helper); +} + +TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsAfterOneAddInQueue) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + EXPECT_CALL(helper, StartFetchingUbertoken()); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", + no_error())); + EXPECT_CALL(helper, StartLogOutUrlFetch()); + + helper.AddAccountToCookie("acc2@gmail.com"); + helper.LogOutAllAccounts(); + + SimulateMergeSessionSuccess(&helper, "token1"); + SimulateLogoutSuccess(&helper); +} + +TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsAfterTwoAddsInQueue) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", + canceled())); + EXPECT_CALL(helper, StartLogOutUrlFetch()); + + helper.AddAccountToCookie("acc1@gmail.com"); + // The Log Out should prevent this AddAccount from being fetched. + helper.AddAccountToCookie("acc2@gmail.com"); + helper.LogOutAllAccounts(); + + SimulateMergeSessionSuccess(&helper, "token1"); + SimulateLogoutSuccess(&helper); +} + +TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsTwice) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + EXPECT_CALL(helper, StartFetchingUbertoken()); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", + no_error())); + EXPECT_CALL(helper, StartLogOutUrlFetch()); + + helper.AddAccountToCookie("acc2@gmail.com"); + SimulateMergeSessionSuccess(&helper, "token1"); + + helper.LogOutAllAccounts(); + // Only one LogOut will be fetched. + helper.LogOutAllAccounts(); + SimulateLogoutSuccess(&helper); +} + +TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsBeforeAdd) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", + no_error())); + EXPECT_CALL(helper, StartLogOutUrlFetch()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); - helper.LogOut("acc2@gmail.com", current_accounts); - SimulateLogoutSuccess(&helper); + helper.AddAccountToCookie("acc2@gmail.com"); SimulateMergeSessionSuccess(&helper, "token1"); - SimulateMergeSessionSuccess(&helper, "token3"); + + helper.LogOutAllAccounts(); + helper.AddAccountToCookie("acc3@gmail.com"); + + SimulateLogoutSuccess(&helper); + // After LogOut the MergeSession should be fetched. + SimulateMergeSessionSuccess(&helper, "token2"); +} + +TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsBeforeLogoutAndAdd) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", + no_error())); + EXPECT_CALL(helper, StartLogOutUrlFetch()); + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", + no_error())); + + helper.AddAccountToCookie("acc2@gmail.com"); + SimulateMergeSessionSuccess(&helper, "token1"); + + helper.LogOutAllAccounts(); + // Second LogOut will never be fetched. + helper.LogOutAllAccounts(); + helper.AddAccountToCookie("acc3@gmail.com"); + + SimulateLogoutSuccess(&helper); + // After LogOut the MergeSession should be fetched. + SimulateMergeSessionSuccess(&helper, "token2"); } TEST_F(GaiaCookieManagerServiceTest, PendingSigninThenSignout) { InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - std::vector<std::string> current_accounts; - current_accounts.push_back("acc2@gmail.com"); - current_accounts.push_back("acc3@gmail.com"); - // From the first Signin. EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", no_error())); @@ -333,13 +424,15 @@ no_error())); // Total sign in 2 times, not enforcing ordered sequences. - EXPECT_CALL(helper, StartFetching()).Times(2); + EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2); helper.AddAccountToCookie("acc1@gmail.com"); - helper.LogOut("acc2@gmail.com", current_accounts); + helper.LogOutAllAccounts(); SimulateMergeSessionSuccess(&helper, "token1"); SimulateLogoutSuccess(&helper); + + helper.AddAccountToCookie("acc3@gmail.com"); SimulateMergeSessionSuccess(&helper, "token3"); } @@ -349,7 +442,7 @@ std::vector<std::string> current_accounts; - EXPECT_CALL(helper, StartFetching()); + EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", canceled())); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", @@ -358,42 +451,12 @@ helper.AddAccountToCookie("acc1@gmail.com"); helper.AddAccountToCookie("acc2@gmail.com"); - helper.LogOut("acc2@gmail.com", current_accounts); + helper.LogOutAllAccounts(); SimulateMergeSessionSuccess(&helper, "token1"); SimulateLogoutSuccess(&helper); } -TEST_F(GaiaCookieManagerServiceTest, DoubleSignout) { - InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); - MockObserver observer(&helper); - - std::vector<std::string> current_accounts1; - current_accounts1.push_back("acc1@gmail.com"); - current_accounts1.push_back("acc2@gmail.com"); - current_accounts1.push_back("acc3@gmail.com"); - - std::vector<std::string> current_accounts2; - current_accounts2.push_back("acc1@gmail.com"); - current_accounts2.push_back("acc3@gmail.com"); - - EXPECT_CALL(helper, StartFetching()).Times(2); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", - canceled())); - EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", - no_error())) - .Times(2); - EXPECT_CALL(helper, StartLogOutUrlFetch()); - - helper.AddAccountToCookie("acc1@gmail.com"); - helper.LogOut("acc2@gmail.com", current_accounts1); - helper.LogOut("acc3@gmail.com", current_accounts2); - - SimulateMergeSessionSuccess(&helper, "token1"); - SimulateLogoutSuccess(&helper); - SimulateMergeSessionSuccess(&helper, "token1"); -} - TEST_F(GaiaCookieManagerServiceTest, ExternalCcResultFetcher) { InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); GaiaCookieManagerService::ExternalCcResultFetcher result_fetcher(&helper);
diff --git a/components/signin/core/common/profile_management_switches.cc b/components/signin/core/common/profile_management_switches.cc index 88c65ab..49af6f1 100644 --- a/components/signin/core/common/profile_management_switches.cc +++ b/components/signin/core/common/profile_management_switches.cc
@@ -79,16 +79,16 @@ } else if (is_new_avatar_menu) { return STATE_NEW_AVATAR_MENU; } else if (not_new_profile_management) { - return STATE_OLD_AVATAR_MENU; + return STATE_NEW_AVATAR_MENU; } else if (not_consistent_identity) { - return STATE_OLD_AVATAR_MENU; + return STATE_NEW_AVATAR_MENU; } // Set the default state #if defined(OS_ANDROID) || defined(OS_IOS) State state = STATE_ACCOUNT_CONSISTENCY; #else - State state = STATE_OLD_AVATAR_MENU; + State state = STATE_NEW_AVATAR_MENU; #endif if (!trial_type.empty()) { @@ -99,7 +99,7 @@ } else if (trial_type == "NewAvatarMenu") { state = STATE_NEW_AVATAR_MENU; } else { - state = STATE_OLD_AVATAR_MENU; + state = STATE_NEW_AVATAR_MENU; } }
diff --git a/components/tracing.gyp b/components/tracing.gyp index 4f8a796c7..8af6dd2 100644 --- a/components/tracing.gyp +++ b/components/tracing.gyp
@@ -23,6 +23,8 @@ '..', ], 'sources': [ + 'tracing/child_memory_dump_manager_delegate_impl.cc', + 'tracing/child_memory_dump_manager_delegate_impl.h', 'tracing/child_trace_message_filter.cc', 'tracing/child_trace_message_filter.h', 'tracing/tracing_messages.cc',
diff --git a/components/tracing/BUILD.gn b/components/tracing/BUILD.gn index c2e05190..5771d93 100644 --- a/components/tracing/BUILD.gn +++ b/components/tracing/BUILD.gn
@@ -4,6 +4,8 @@ source_set("tracing") { sources = [ + "child_memory_dump_manager_delegate_impl.cc", + "child_memory_dump_manager_delegate_impl.h", "child_trace_message_filter.cc", "child_trace_message_filter.h", "tracing_messages.cc",
diff --git a/components/tracing/child_memory_dump_manager_delegate_impl.cc b/components/tracing/child_memory_dump_manager_delegate_impl.cc new file mode 100644 index 0000000..5595b14 --- /dev/null +++ b/components/tracing/child_memory_dump_manager_delegate_impl.cc
@@ -0,0 +1,71 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/tracing/child_memory_dump_manager_delegate_impl.h" + +#include "base/single_thread_task_runner.h" +#include "components/tracing/child_trace_message_filter.h" + +namespace tracing { + +// static +ChildMemoryDumpManagerDelegateImpl* +ChildMemoryDumpManagerDelegateImpl::GetInstance() { + return Singleton< + ChildMemoryDumpManagerDelegateImpl, + LeakySingletonTraits<ChildMemoryDumpManagerDelegateImpl>>::get(); +} + +ChildMemoryDumpManagerDelegateImpl::ChildMemoryDumpManagerDelegateImpl() + : ctmf_(nullptr) { + base::trace_event::MemoryDumpManager::GetInstance()->SetDelegate(this); +} + +ChildMemoryDumpManagerDelegateImpl::~ChildMemoryDumpManagerDelegateImpl() { +} + +void ChildMemoryDumpManagerDelegateImpl::SetChildTraceMessageFilter( + ChildTraceMessageFilter* ctmf) { + // Check that we are either registering the CTMF or tearing it down, but not + // replacing a valid instance with another one (should never happen). + DCHECK(ctmf_ == nullptr || (ctmf == nullptr && ctmf_task_runner_ != nullptr)); + ctmf_ = ctmf; + ctmf_task_runner_ = ctmf ? (ctmf->ipc_message_loop()) : nullptr; +} + +// Invoked in child processes by the MemoryDumpManager. +void ChildMemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::trace_event::MemoryDumpCallback& callback) { + // Bail out if we receive a dump request from the manager before the + // ChildTraceMessageFilter has been initialized. + if (!ctmf_task_runner_) { + if (!callback.is_null()) + callback.Run(args.dump_guid, false /* success */); + return; + } + + // Make sure we access |ctmf_| only on the thread where it lives to avoid + // races on shutdown. + if (!ctmf_task_runner_->BelongsToCurrentThread()) { + ctmf_task_runner_->PostTask( + FROM_HERE, + base::Bind(&ChildMemoryDumpManagerDelegateImpl::RequestGlobalMemoryDump, + base::Unretained(this), args, callback)); + return; + } + + // The ChildTraceMessageFilter could have been destroyed while hopping on the + // right thread. If this is the case, bail out. + if (!ctmf_) { + if (!callback.is_null()) + callback.Run(args.dump_guid, false /* success */); + return; + } + + // Send the request up to the browser process' MessageDumpmanager. + ctmf_->SendGlobalMemoryDumpRequest(args, callback); +} + +} // namespace tracing
diff --git a/components/tracing/child_memory_dump_manager_delegate_impl.h b/components/tracing/child_memory_dump_manager_delegate_impl.h new file mode 100644 index 0000000..03069537 --- /dev/null +++ b/components/tracing/child_memory_dump_manager_delegate_impl.h
@@ -0,0 +1,56 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_TRACING_CHILD_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_ +#define COMPONENTS_TRACING_CHILD_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_ + +#include "base/trace_event/memory_dump_manager.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/singleton.h" + +namespace base { +class SingleThreadTaskRunner; +} // namespace base + +namespace tracing { + +class ChildTraceMessageFilter; + +// This class is a simple proxy class between the MemoryDumpManager and the +// ChildTraceMessageFilter. It's only purpose is to adapt the lifetime of +// CTMF to the demands of MDM, which expects the delegate to be thread-safe +// and long lived. CTMF, instead, can be torn down during browser shutdown. +// This class is registered as MDM delegate in child processes and handles +// gracefully (and thread-safely) failures in the case of a lack of the CTMF. +class ChildMemoryDumpManagerDelegateImpl + : public base::trace_event::MemoryDumpManagerDelegate { + public: + static ChildMemoryDumpManagerDelegateImpl* GetInstance(); + + // base::trace_event::MemoryDumpManagerDelegate implementation. + void RequestGlobalMemoryDump( + const base::trace_event::MemoryDumpRequestArgs& args, + const base::trace_event::MemoryDumpCallback& callback) override; + + void SetChildTraceMessageFilter(ChildTraceMessageFilter* ctmf); + + private: + friend struct DefaultSingletonTraits<ChildMemoryDumpManagerDelegateImpl>; + + ChildMemoryDumpManagerDelegateImpl(); + ~ChildMemoryDumpManagerDelegateImpl() override; + + ChildTraceMessageFilter* ctmf_; // Not owned. + + // The SingleThreadTaskRunner where the |ctmf_| lives. + // It is NULL iff |cmtf_| is NULL. + scoped_refptr<base::SingleThreadTaskRunner> ctmf_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(ChildMemoryDumpManagerDelegateImpl); +}; + +} // namespace tracing + +#endif // COMPONENTS_TRACING_CHILD_MEMORY_DUMP_MANAGER_DELEGATE_IMPL_H_
diff --git a/components/tracing/child_trace_message_filter.cc b/components/tracing/child_trace_message_filter.cc index d20ba7b..3594dce 100644 --- a/components/tracing/child_trace_message_filter.cc +++ b/components/tracing/child_trace_message_filter.cc
@@ -6,6 +6,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/trace_event/trace_event.h" +#include "components/tracing/child_memory_dump_manager_delegate_impl.h" #include "components/tracing/tracing_messages.h" #include "ipc/ipc_channel.h" @@ -16,14 +17,20 @@ ChildTraceMessageFilter::ChildTraceMessageFilter( base::MessageLoopProxy* ipc_message_loop) : sender_(NULL), - ipc_message_loop_(ipc_message_loop) {} + ipc_message_loop_(ipc_message_loop), + pending_memory_dump_guid_(0) { +} void ChildTraceMessageFilter::OnFilterAdded(IPC::Sender* sender) { sender_ = sender; sender_->Send(new TracingHostMsg_ChildSupportsTracing()); + ChildMemoryDumpManagerDelegateImpl::GetInstance()->SetChildTraceMessageFilter( + this); } void ChildTraceMessageFilter::OnFilterRemoved() { + ChildMemoryDumpManagerDelegateImpl::GetInstance()->SetChildTraceMessageFilter( + nullptr); sender_ = NULL; } @@ -175,8 +182,9 @@ // Sent by the Browser's MemoryDumpManager when coordinating a global dump. void ChildTraceMessageFilter::OnProcessMemoryDumpRequest( const base::trace_event::MemoryDumpRequestArgs& args) { - // TODO(primiano): create local dump and send a response back to the browser. - NOTIMPLEMENTED(); + base::trace_event::MemoryDumpManager::GetInstance()->CreateProcessDump(args); + sender_->Send( + new TracingHostMsg_ProcessMemoryDumpResponse(args.dump_guid, true)); } // Initiates a dump request, asking the Browser's MemoryDumpManager to @@ -187,18 +195,28 @@ void ChildTraceMessageFilter::SendGlobalMemoryDumpRequest( const base::trace_event::MemoryDumpRequestArgs& args, const base::trace_event::MemoryDumpCallback& callback) { - // TODO(primiano): implement the logic to send the request to the browser - // process and keep track of that. - NOTIMPLEMENTED(); + // If there is already another dump request pending from this child process, + // there is no point bothering the Browser's MemoryDumpManager. + if (pending_memory_dump_guid_) { + if (!callback.is_null()) + callback.Run(args.dump_guid, false); + return; + } + + pending_memory_dump_guid_ = args.dump_guid; + pending_memory_dump_callback_ = callback; + sender_->Send(new TracingHostMsg_GlobalMemoryDumpRequest(args)); } // Sent by the Browser's MemoryDumpManager in response of a dump request // initiated by this child process. void ChildTraceMessageFilter::OnGlobalMemoryDumpResponse(uint64 dump_guid, bool success) { - // TODO(primiano): implement the logic to handle the global response from - // the browser and clear up the bookkeeping. - NOTIMPLEMENTED(); + DCHECK_NE(0U, pending_memory_dump_guid_); + pending_memory_dump_guid_ = 0; + if (pending_memory_dump_callback_.is_null()) + return; + pending_memory_dump_callback_.Run(dump_guid, success); } } // namespace tracing
diff --git a/components/tracing/child_trace_message_filter.h b/components/tracing/child_trace_message_filter.h index d3d934097..080ea04 100644 --- a/components/tracing/child_trace_message_filter.h +++ b/components/tracing/child_trace_message_filter.h
@@ -30,6 +30,8 @@ const base::trace_event::MemoryDumpRequestArgs& args, const base::trace_event::MemoryDumpCallback& callback); + base::MessageLoopProxy* ipc_message_loop() const { return ipc_message_loop_; } + protected: ~ChildTraceMessageFilter() override; @@ -65,6 +67,13 @@ IPC::Sender* sender_; base::MessageLoopProxy* ipc_message_loop_; + // guid of the outstanding request (to the Browser's MemoryDumpManager), if + // any. 0 if there is no request pending. + uint64 pending_memory_dump_guid_; + + // callback of the outstanding memory dump request, if any. + base::trace_event::MemoryDumpCallback pending_memory_dump_callback_; + DISALLOW_COPY_AND_ASSIGN(ChildTraceMessageFilter); };
diff --git a/components/tracing_nacl.gyp b/components/tracing_nacl.gyp index 144117f9..d0fc45d 100644 --- a/components/tracing_nacl.gyp +++ b/components/tracing_nacl.gyp
@@ -34,6 +34,8 @@ 'build_nonsfi_helper': 1, }, 'sources': [ + 'tracing/child_memory_dump_manager_delegate_impl.cc', + 'tracing/child_memory_dump_manager_delegate_impl.h', 'tracing/child_trace_message_filter.cc', 'tracing/child_trace_message_filter.h', 'tracing/tracing_messages.cc',
diff --git a/components/web_contents_delegate_android/validation_message_bubble_android.cc b/components/web_contents_delegate_android/validation_message_bubble_android.cc index 754b6085..a577636 100644 --- a/components/web_contents_delegate_android/validation_message_bubble_android.cc +++ b/components/web_contents_delegate_android/validation_message_bubble_android.cc
@@ -17,12 +17,15 @@ namespace { -inline ContentViewCore* GetContentViewCoreFrom(RenderWidgetHost* widget_host) { - return ContentViewCore::FromWebContents( - content::WebContents::FromRenderViewHost( +base::android::ScopedJavaLocalRef<jobject> GetJavaContentViewCoreFrom( + RenderWidgetHost* widget_host) { + ContentViewCore* content_view_core = + ContentViewCore::FromWebContents(content::WebContents::FromRenderViewHost( content::RenderViewHost::From(widget_host))); + if (!content_view_core) + return base::android::ScopedJavaLocalRef<jobject>(); + return content_view_core->GetJavaObject(); } - } namespace web_contents_delegate_android { @@ -32,11 +35,16 @@ const gfx::Rect& anchor_in_root_view, const base::string16& main_text, const base::string16& sub_text) { + base::android::ScopedJavaLocalRef<jobject> java_content_view_core = + GetJavaContentViewCoreFrom(widget_host); + if (java_content_view_core.is_null()) + return; + JNIEnv* env = base::android::AttachCurrentThread(); java_validation_message_bubble_.Reset( Java_ValidationMessageBubble_createAndShow( env, - GetContentViewCoreFrom(widget_host)->GetJavaObject().obj(), + java_content_view_core.obj(), anchor_in_root_view.x(), anchor_in_root_view.y(), anchor_in_root_view.width(), @@ -52,10 +60,15 @@ void ValidationMessageBubbleAndroid::SetPositionRelativeToAnchor( RenderWidgetHost* widget_host, const gfx::Rect& anchor_in_root_view) { + base::android::ScopedJavaLocalRef<jobject> java_content_view_core = + GetJavaContentViewCoreFrom(widget_host); + if (java_content_view_core.is_null()) + return; + Java_ValidationMessageBubble_setPositionRelativeToAnchor( base::android::AttachCurrentThread(), java_validation_message_bubble_.obj(), - GetContentViewCoreFrom(widget_host)->GetJavaObject().obj(), + java_content_view_core.obj(), anchor_in_root_view.x(), anchor_in_root_view.y(), anchor_in_root_view.width(),
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index a722c0c..dee927a 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -223,6 +223,7 @@ "dinput8.lib", "dwmapi.lib", "dxguid.lib", + "oleacc.lib", "sensorsapi.lib", "portabledeviceguids.lib", ]
diff --git a/content/browser/android/content_readback_handler.cc b/content/browser/android/content_readback_handler.cc index 5964a78..6ff62e43 100644 --- a/content/browser/android/content_readback_handler.cc +++ b/content/browser/android/content_readback_handler.cc
@@ -111,7 +111,7 @@ java_bitmap = gfx::ConvertToJavaBitmap(&bitmap); Java_ContentReadbackHandler_notifyGetBitmapFinished( - env, java_obj_.obj(), readback_id, java_bitmap.obj()); + env, java_obj_.obj(), readback_id, java_bitmap.obj(), response); } // static
diff --git a/content/browser/android/content_video_view.cc b/content/browser/android/content_video_view.cc index 1081bd64..2a5ce04 100644 --- a/content/browser/android/content_video_view.cc +++ b/content/browser/android/content_video_view.cc
@@ -198,11 +198,17 @@ JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject() { ContentViewCore* content_view_core = manager_->GetContentViewCore(); JNIEnv* env = AttachCurrentThread(); + + base::android::ScopedJavaLocalRef<jobject> j_content_view_core = + content_view_core->GetJavaObject(); + if (j_content_view_core.is_null()) + return JavaObjectWeakGlobalRef(env, nullptr); + return JavaObjectWeakGlobalRef( env, Java_ContentVideoView_createContentVideoView( env, - content_view_core->GetJavaObject().obj(), + j_content_view_core.obj(), reinterpret_cast<intptr_t>(this)).obj()); } } // namespace content
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 38886f9..0202db0 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc
@@ -214,7 +214,7 @@ JNIEnv* env, jobject obj, WebContents* web_contents, - jobject view_android, + jobject view_android_delegate, ui::WindowAndroid* window_android, jobject java_bridge_retained_object_set) : WebContentsObserver(web_contents), @@ -222,7 +222,7 @@ web_contents_(static_cast<WebContentsImpl*>(web_contents)), root_layer_(cc::SolidColorLayer::Create()), dpi_scale_(GetPrimaryDisplayDeviceScaleFactor()), - view_android_(new ui::ViewAndroid(view_android, window_android)), + view_android_(new ui::ViewAndroid(view_android_delegate, window_android)), window_android_(window_android), device_orientation_(0), accessibility_enabled_(false) { @@ -552,36 +552,42 @@ } } -bool ContentViewCoreImpl::FilterInputEvent(const blink::WebInputEvent& event) { +InputEventAckState ContentViewCoreImpl::FilterInputEvent( + const blink::WebInputEvent& event) { if (event.type != WebInputEvent::GestureTap && event.type != WebInputEvent::GestureDoubleTap && event.type != WebInputEvent::GestureLongTap && event.type != WebInputEvent::GestureLongPress && - event.type != WebInputEvent::GestureFlingCancel) - return false; + event.type != WebInputEvent::GestureFlingCancel) { + return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; + } JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env); if (j_obj.is_null()) - return false; + return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; if (event.type == WebInputEvent::GestureFlingCancel) { // If no fling is active, either in the compositor or externally-driven, // there's no need to explicitly cancel the fling. bool may_need_fling_cancel = Java_ContentViewCore_isScrollInProgress(env, j_obj.obj()); - return !may_need_fling_cancel; + return may_need_fling_cancel ? INPUT_EVENT_ACK_STATE_NOT_CONSUMED + : INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; } const blink::WebGestureEvent& gesture = static_cast<const blink::WebGestureEvent&>(event); int gesture_type = ToGestureEventType(event.type); - return Java_ContentViewCore_filterTapOrPressEvent(env, - j_obj.obj(), - gesture_type, - gesture.x * dpi_scale(), - gesture.y * dpi_scale()); + if (Java_ContentViewCore_filterTapOrPressEvent(env, + j_obj.obj(), + gesture_type, + gesture.x * dpi_scale(), + gesture.y * dpi_scale())) { + return INPUT_EVENT_ACK_STATE_CONSUMED; + } + return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; // TODO(jdduke): Also report double-tap UMA, crbug/347568. } @@ -1402,11 +1408,12 @@ jlong Init(JNIEnv* env, jobject obj, jobject web_contents, - jobject view_android, + jobject view_android_delegate, jlong window_android, jobject retained_objects_set) { ContentViewCoreImpl* view = new ContentViewCoreImpl( - env, obj, WebContents::FromJavaWebContents(web_contents), view_android, + env, obj, WebContents::FromJavaWebContents(web_contents), + view_android_delegate, reinterpret_cast<ui::WindowAndroid*>(window_android), retained_objects_set); return reinterpret_cast<intptr_t>(view);
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index 2b936a1..94d4cd4 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h
@@ -239,7 +239,7 @@ bool HasFocus(); void OnGestureEventAck(const blink::WebGestureEvent& event, InputEventAckState ack_result); - bool FilterInputEvent(const blink::WebInputEvent& event); + InputEventAckState FilterInputEvent(const blink::WebInputEvent& event); void OnSelectionChanged(const std::string& text); void OnSelectionEvent(ui::SelectionEventType event, const gfx::PointF& anchor_position);
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc index 470743a5..48891cd 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
@@ -83,11 +83,10 @@ : public StreamTextureFactorySynchronousImpl::ContextProvider { public: VideoContextProvider( - scoped_ptr<gpu::GLInProcessContext> gl_in_process_context) - : gl_in_process_context_(gl_in_process_context.get()) { - context_provider_ = webkit::gpu::ContextProviderInProcess::Create( - WrapContext(gl_in_process_context.Pass(), GetDefaultAttribs()), - "Video-Offscreen-main-thread"); + scoped_refptr<cc::ContextProvider> context_provider, + gpu::GLInProcessContext* gl_in_process_context) + : context_provider_(context_provider), + gl_in_process_context_(gl_in_process_context) { context_provider_->BindToCurrentThread(); } @@ -262,9 +261,15 @@ attributes.shareResources = false; // This needs to run in on-screen |service_| context due to SurfaceTexture // limitations. - video_context_provider_ = new VideoContextProvider(CreateContextHolder( - attributes, service_, gpu::GLInProcessContextSharedMemoryLimits(), - false)); + scoped_ptr<gpu::GLInProcessContext> context = + CreateContextHolder(attributes, service_, + gpu::GLInProcessContextSharedMemoryLimits(), false); + gpu::GLInProcessContext* context_ptr = context.get(); + video_context_provider_ = + new VideoContextProvider(webkit::gpu::ContextProviderInProcess::Create( + WrapContext(context.Pass(), attributes), + "Video-Offscreen-main-thread"), + context_ptr); } return video_context_provider_; }
diff --git a/content/browser/background_sync/background_sync.proto b/content/browser/background_sync/background_sync.proto index 4f93d97..3717ca1 100644 --- a/content/browser/background_sync/background_sync.proto +++ b/content/browser/background_sync/background_sync.proto
@@ -21,7 +21,7 @@ message BackgroundSyncRegistrationProto { required int64 id = 1; - required string name = 2; + required string tag = 2; required bool fire_once = 3; required int64 min_period = 4; required SyncNetworkState network_state = 5;
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index d997652..8c3fa98 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -73,7 +73,7 @@ void BackgroundSyncManager::Unregister( const GURL& origin, int64 sw_registration_id, - const std::string& sync_registration_name, + const std::string& sync_registration_tag, BackgroundSyncRegistration::RegistrationId sync_registration_id, const StatusCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -86,14 +86,14 @@ op_scheduler_.ScheduleOperation(base::Bind( &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(), - origin, sw_registration_id, sync_registration_name, sync_registration_id, + origin, sw_registration_id, sync_registration_tag, sync_registration_id, MakeStatusCompletion(callback))); } void BackgroundSyncManager::GetRegistration( const GURL& origin, int64 sw_registration_id, - const std::string sync_registration_name, + const std::string sync_registration_tag, const StatusAndRegistrationCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -107,7 +107,7 @@ op_scheduler_.ScheduleOperation(base::Bind( &BackgroundSyncManager::GetRegistrationImpl, weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id, - sync_registration_name, MakeStatusAndRegistrationCompletion(callback))); + sync_registration_tag, MakeStatusAndRegistrationCompletion(callback))); } void BackgroundSyncManager::OnRegistrationDeleted(int64 registration_id, @@ -194,10 +194,10 @@ } BackgroundSyncRegistration* registration = - ®istrations->name_to_registration_map[registration_proto.name()]; + ®istrations->tag_to_registration_map[registration_proto.tag()]; registration->id = registration_proto.id(); - registration->name = registration_proto.name(); + registration->tag = registration_proto.tag(); registration->fire_once = registration_proto.fire_once(); registration->min_period = registration_proto.min_period(); registration->network_state = registration_proto.network_state(); @@ -233,7 +233,7 @@ } BackgroundSyncRegistration existing_registration; - if (LookupRegistration(sw_registration_id, sync_registration.name, + if (LookupRegistration(sw_registration_id, sync_registration.tag, &existing_registration)) { if (existing_registration.Equals(sync_registration)) { base::MessageLoop::current()->PostTask( @@ -306,7 +306,7 @@ bool BackgroundSyncManager::LookupRegistration( int64 sw_registration_id, - const std::string& sync_registration_name, + const std::string& sync_registration_tag, BackgroundSyncRegistration* existing_registration) { SWIdToRegistrationsMap::iterator it = sw_to_registrations_map_.find(sw_registration_id); @@ -314,14 +314,13 @@ return false; const BackgroundSyncRegistrations& registrations = it->second; - const auto name_and_registration_iter = - registrations.name_to_registration_map.find(sync_registration_name); - if (name_and_registration_iter == - registrations.name_to_registration_map.end()) + const auto tag_and_registration_iter = + registrations.tag_to_registration_map.find(sync_registration_tag); + if (tag_and_registration_iter == registrations.tag_to_registration_map.end()) return false; if (existing_registration) - *existing_registration = name_and_registration_iter->second; + *existing_registration = tag_and_registration_iter->second; return true; } @@ -336,14 +335,14 @@ BackgroundSyncRegistrationsProto registrations_proto; registrations_proto.set_next_registration_id(registrations.next_id); - for (const auto& name_and_registration : - registrations.name_to_registration_map) { + for (const auto& tag_and_registration : + registrations.tag_to_registration_map) { const BackgroundSyncRegistration& registration = - name_and_registration.second; + tag_and_registration.second; BackgroundSyncRegistrationProto* registration_proto = registrations_proto.add_registration(); registration_proto->set_id(registration.id); - registration_proto->set_name(registration.name); + registration_proto->set_tag(registration.tag); registration_proto->set_fire_once(registration.fire_once); registration_proto->set_min_period(registration.min_period); registration_proto->set_network_state(registration.network_state); @@ -386,14 +385,14 @@ void BackgroundSyncManager::RemoveRegistrationFromMap( int64 sw_registration_id, - const std::string& sync_registration_name) { + const std::string& sync_registration_tag) { DCHECK( - LookupRegistration(sw_registration_id, sync_registration_name, nullptr)); + LookupRegistration(sw_registration_id, sync_registration_tag, nullptr)); BackgroundSyncRegistrations* registrations = &sw_to_registrations_map_[sw_registration_id]; - registrations->name_to_registration_map.erase(sync_registration_name); + registrations->tag_to_registration_map.erase(sync_registration_tag); } void BackgroundSyncManager::AddRegistrationToMap( @@ -404,7 +403,7 @@ BackgroundSyncRegistrations* registrations = &sw_to_registrations_map_[sw_registration_id]; - registrations->name_to_registration_map[sync_registration.name] = + registrations->tag_to_registration_map[sync_registration.tag] = sync_registration; } @@ -431,7 +430,7 @@ void BackgroundSyncManager::UnregisterImpl( const GURL& origin, int64 sw_registration_id, - const std::string& sync_registration_name, + const std::string& sync_registration_tag, BackgroundSyncRegistration::RegistrationId sync_registration_id, const StatusCallback& callback) { if (disabled_) { @@ -441,7 +440,7 @@ } BackgroundSyncRegistration existing_registration; - if (!LookupRegistration(sw_registration_id, sync_registration_name, + if (!LookupRegistration(sw_registration_id, sync_registration_tag, &existing_registration) || existing_registration.id != sync_registration_id) { base::MessageLoop::current()->PostTask( @@ -449,7 +448,7 @@ return; } - RemoveRegistrationFromMap(sw_registration_id, sync_registration_name); + RemoveRegistrationFromMap(sw_registration_id, sync_registration_tag); StoreRegistrations( origin, sw_registration_id, @@ -483,7 +482,7 @@ void BackgroundSyncManager::GetRegistrationImpl( const GURL& origin, int64 sw_registration_id, - const std::string sync_registration_name, + const std::string sync_registration_tag, const StatusAndRegistrationCallback& callback) { if (disabled_) { base::MessageLoop::current()->PostTask( @@ -493,7 +492,7 @@ } BackgroundSyncRegistration out_registration; - if (!LookupRegistration(sw_registration_id, sync_registration_name, + if (!LookupRegistration(sw_registration_id, sync_registration_tag, &out_registration)) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND,
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h index ca910bf..82c7f438 100644 --- a/content/browser/background_sync/background_sync_manager.h +++ b/content/browser/background_sync/background_sync_manager.h
@@ -55,14 +55,14 @@ BackgroundSyncRegistration() {} bool Equals(const BackgroundSyncRegistration& other) { - return this->name == other.name && this->fire_once == other.fire_once && + return this->tag == other.tag && this->fire_once == other.fire_once && this->min_period == other.min_period && network_state == other.network_state && power_state == other.power_state; } RegistrationId id = kInvalidRegistrationId; - std::string name; + std::string tag; bool fire_once = true; int64 min_period = 0; SyncNetworkState network_state = NETWORK_STATE_ONLINE; @@ -70,7 +70,7 @@ }; struct CONTENT_EXPORT BackgroundSyncRegistrations { - using NameToRegistrationMap = + using TagToRegistrationMap = std::map<std::string, BackgroundSyncRegistration>; static const BackgroundSyncRegistration::RegistrationId kInitialId; @@ -79,7 +79,7 @@ BackgroundSyncRegistration::RegistrationId next_id); ~BackgroundSyncRegistrations(); - NameToRegistrationMap name_to_registration_map; + TagToRegistrationMap tag_to_registration_map; BackgroundSyncRegistration::RegistrationId next_id; }; @@ -92,7 +92,7 @@ ~BackgroundSyncManager() override; // Stores the given background sync registration and adds it to the scheduling - // queue. Overwrites any existing registration with the same name but + // queue. Overwrites any existing registration with the same tag but // different parameters (other than the id). Calls |callback| with ErrorTypeOK // and the accepted registration on success. The accepted registration will // have a unique id. It may also have altered parameters if the user or UA @@ -102,15 +102,15 @@ const BackgroundSyncRegistration& sync_registration, const StatusAndRegistrationCallback& callback); - // Removes the background sync registration with |sync_registration_name| if + // Removes the background sync registration with |sync_registration_tag| if // the |sync_registration_id| matches. |sync_registration_id| will not match - // if, for instance, a new registration with the same name has replaced it. + // if, for instance, a new registration with the same tag has replaced it. // Calls |callback| with ErrorTypeNotFound if no match is found. Calls // |callback| with ErrorTypeOK on success. void Unregister( const GURL& origin, int64 sw_registration_id, - const std::string& sync_registration_name, + const std::string& sync_registration_tag, BackgroundSyncRegistration::RegistrationId sync_registration_id, const StatusCallback& callback); @@ -119,7 +119,7 @@ // exist. Calls |callback| with ErrorTypeOK on success. void GetRegistration(const GURL& origin, int64 sw_registration_id, - const std::string sync_registration_name, + const std::string sync_registration_tag, const StatusAndRegistrationCallback& callback); // ServiceWorkerContextObserver overrides. @@ -166,7 +166,7 @@ // Returns the existing registration in |existing_registration| if it is not // null. bool LookupRegistration(int64 sw_registration_id, - const std::string& sync_registration_name, + const std::string& sync_registration_tag, BackgroundSyncRegistration* existing_registration); // Store all registrations for a given |sw_registration_id|. @@ -176,7 +176,7 @@ // Removes the registration if it is in the map. void RemoveRegistrationFromMap(int64 sw_registration_id, - const std::string& sync_registration_name); + const std::string& sync_registration_tag); void AddRegistrationToMap( int64 sw_registration_id, @@ -202,7 +202,7 @@ void UnregisterImpl( const GURL& origin, int64 sw_registration_id, - const std::string& sync_registration_name, + const std::string& sync_registration_tag, BackgroundSyncRegistration::RegistrationId sync_registration_id, const StatusCallback& callback); void UnregisterDidStore( @@ -213,7 +213,7 @@ // GetRegistration callbacks void GetRegistrationImpl(const GURL& origin, int64 sw_registration_id, - const std::string sync_registration_name, + const std::string sync_registration_tag, const StatusAndRegistrationCallback& callback); // OnRegistrationDeleted callbacks
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index 805c5cd..7540697 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -141,8 +141,8 @@ sync_reg_2_(BackgroundSyncManager::BackgroundSyncRegistration()), callback_error_(BackgroundSyncManager::ERROR_TYPE_OK), callback_sw_status_code_(SERVICE_WORKER_OK) { - sync_reg_1_.name = "foo"; - sync_reg_2_.name = "bar"; + sync_reg_1_.tag = "foo"; + sync_reg_2_.tag = "bar"; } void SetUp() override { @@ -228,7 +228,7 @@ sync_registration) { bool was_called = false; background_sync_manager_->Unregister( - GURL(kOrigin), sw_registration_id, sync_registration.name, + GURL(kOrigin), sw_registration_id, sync_registration.tag, sync_registration.id, base::Bind(&BackgroundSyncManagerTest::StatusCallback, base::Unretained(this), &was_called)); @@ -237,24 +237,24 @@ return callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK; } - bool GetRegistration(const std::string& sync_registration_name) { + bool GetRegistration(const std::string& sync_registration_tag) { return GetRegistrationWithServiceWorkerId(sw_registration_id_1_, - sync_registration_name); + sync_registration_tag); } bool GetRegistrationWithServiceWorkerId( int64 sw_registration_id, - const std::string& sync_registration_name) { + const std::string& sync_registration_tag) { bool was_called = false; background_sync_manager_->GetRegistration( - GURL(kOrigin), sw_registration_id, sync_registration_name, + GURL(kOrigin), sw_registration_id, sync_registration_tag, base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback, base::Unretained(this), &was_called)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(was_called); if (callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK) - EXPECT_TRUE(sync_registration_name == callback_registration_.name); + EXPECT_TRUE(sync_registration_tag == callback_registration_.tag); return callback_error_ == BackgroundSyncManager::ERROR_TYPE_OK; } @@ -300,7 +300,7 @@ TEST_F(BackgroundSyncManagerTest, RegistractionIntact) { EXPECT_TRUE(Register(sync_reg_1_)); - EXPECT_STREQ(sync_reg_1_.name.c_str(), callback_registration_.name.c_str()); + EXPECT_STREQ(sync_reg_1_.tag.c_str(), callback_registration_.tag.c_str()); EXPECT_NE( BackgroundSyncManager::BackgroundSyncRegistration::kInvalidRegistrationId, callback_registration_.id); @@ -332,7 +332,7 @@ EXPECT_FALSE(Register(sync_reg_1_)); manager->set_corrupt_backend(false); EXPECT_FALSE(Register(sync_reg_1_)); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, TwoRegistrations) { @@ -341,32 +341,32 @@ } TEST_F(BackgroundSyncManagerTest, GetRegistrationNonExisting) { - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, GetRegistrationExisting) { EXPECT_TRUE(Register(sync_reg_1_)); - EXPECT_TRUE(GetRegistration(sync_reg_1_.name)); - EXPECT_FALSE(GetRegistration(sync_reg_2_.name)); + EXPECT_TRUE(GetRegistration(sync_reg_1_.tag)); + EXPECT_FALSE(GetRegistration(sync_reg_2_.tag)); } TEST_F(BackgroundSyncManagerTest, GetRegistrationBadBackend) { TestBackgroundSyncManager* manager = UseTestBackgroundSyncManager(); EXPECT_TRUE(Register(sync_reg_1_)); manager->set_corrupt_backend(true); - EXPECT_TRUE(GetRegistration(sync_reg_1_.name)); + EXPECT_TRUE(GetRegistration(sync_reg_1_.tag)); EXPECT_FALSE(Register(sync_reg_2_)); // Registration should have discovered the bad backend and disabled the // BackgroundSyncManager. - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); manager->set_corrupt_backend(false); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, Unregister) { EXPECT_TRUE(Register(sync_reg_1_)); EXPECT_TRUE(Unregister(callback_registration_)); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, UnregisterWrongId) { @@ -390,7 +390,7 @@ EXPECT_TRUE(Register(sync_reg_1_)); EXPECT_TRUE(Register(sync_reg_2_)); EXPECT_TRUE(Unregister(callback_registration_)); - EXPECT_TRUE(GetRegistration(sync_reg_1_.name)); + EXPECT_TRUE(GetRegistration(sync_reg_1_.tag)); EXPECT_TRUE(Register(sync_reg_2_)); } @@ -404,8 +404,8 @@ // Unregister should have discovered the bad backend and disabled the // BackgroundSyncManager. manager->set_corrupt_backend(false); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); - EXPECT_FALSE(GetRegistration(sync_reg_2_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); + EXPECT_FALSE(GetRegistration(sync_reg_2_.tag)); } TEST_F(BackgroundSyncManagerTest, RegistrationIncreasesId) { @@ -415,7 +415,7 @@ BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId cur_id = callback_registration_.id; - EXPECT_TRUE(GetRegistration(sync_reg_1_.name)); + EXPECT_TRUE(GetRegistration(sync_reg_1_.tag)); EXPECT_TRUE(Register(sync_reg_2_)); EXPECT_LT(cur_id, callback_registration_.id); cur_id = callback_registration_.id; @@ -431,8 +431,8 @@ background_sync_manager_ = BackgroundSyncManager::Create(helper_->context_wrapper()); - EXPECT_TRUE(GetRegistration(sync_reg_1_.name)); - EXPECT_FALSE(GetRegistration(sync_reg_2_.name)); + EXPECT_TRUE(GetRegistration(sync_reg_1_.tag)); + EXPECT_FALSE(GetRegistration(sync_reg_2_.tag)); } TEST_F(BackgroundSyncManagerTest, RebootRecoveryTwoServiceWorkers) { @@ -443,18 +443,18 @@ BackgroundSyncManager::Create(helper_->context_wrapper()); EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_, - sync_reg_1_.name)); + sync_reg_1_.tag)); EXPECT_FALSE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_, - sync_reg_2_.name)); + sync_reg_2_.tag)); EXPECT_FALSE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_, - sync_reg_1_.name)); + sync_reg_1_.tag)); EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_, - sync_reg_2_.name)); + sync_reg_2_.tag)); EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_1_, - sync_reg_1_.name)); + sync_reg_1_.tag)); EXPECT_TRUE(GetRegistrationWithServiceWorkerId(sw_registration_id_2_, - sync_reg_2_.name)); + sync_reg_2_.tag)); EXPECT_TRUE(RegisterWithServiceWorkerId(sw_registration_id_1_, sync_reg_2_)); EXPECT_TRUE(RegisterWithServiceWorkerId(sw_registration_id_2_, sync_reg_1_)); @@ -468,7 +468,7 @@ manager->DoInit(); EXPECT_FALSE(Register(sync_reg_1_)); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, SequentialOperations) { @@ -490,12 +490,12 @@ GURL(kOrigin), sw_registration_id_1_, sync_reg_1_, base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback, base::Unretained(this), ®ister_called)); - manager->Unregister(GURL(kOrigin), sw_registration_id_1_, sync_reg_1_.name, + manager->Unregister(GURL(kOrigin), sw_registration_id_1_, sync_reg_1_.tag, kExpectedInitialId, base::Bind(&BackgroundSyncManagerTest::StatusCallback, base::Unretained(this), &unregister_called)); manager->GetRegistration( - GURL(kOrigin), sw_registration_id_1_, sync_reg_1_.name, + GURL(kOrigin), sw_registration_id_1_, sync_reg_1_.tag, base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback, base::Unretained(this), &get_registration_called)); @@ -533,7 +533,7 @@ TEST_F(BackgroundSyncManagerTest, UnregisterServiceWorker) { EXPECT_TRUE(Register(sync_reg_1_)); UnregisterServiceWorker(sw_registration_id_1_); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, @@ -562,14 +562,14 @@ EXPECT_EQ(BackgroundSyncManager::ERROR_TYPE_STORAGE, callback_error_); manager->set_delay_backend(false); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, DeleteAndStartOverServiceWorkerContext) { EXPECT_TRUE(Register(sync_reg_1_)); helper_->context()->ScheduleDeleteAndStartOver(); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); } TEST_F(BackgroundSyncManagerTest, DisabledManagerWorksAfterBrowserRestart) { @@ -584,13 +584,13 @@ // The manager is now disabled and not accepting new requests until browser // restart or notification that the storage has been wiped. manager->set_corrupt_backend(false); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); EXPECT_FALSE(Register(sync_reg_2_)); // Simulate restarting the browser by creating a new BackgroundSyncManager. background_sync_manager_.reset( new TestBackgroundSyncManager(helper_->context_wrapper())); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); EXPECT_TRUE(Register(sync_reg_1_)); } @@ -618,8 +618,8 @@ EXPECT_TRUE(called); EXPECT_TRUE(Register(sync_reg_2_)); - EXPECT_FALSE(GetRegistration(sync_reg_1_.name)); - EXPECT_TRUE(GetRegistration(sync_reg_2_.name)); + EXPECT_FALSE(GetRegistration(sync_reg_1_.tag)); + EXPECT_TRUE(GetRegistration(sync_reg_2_.tag)); } TEST_F(BackgroundSyncManagerTest, RegistrationEqualsId) { @@ -631,11 +631,11 @@ EXPECT_TRUE(reg_1.Equals(reg_2)); } -TEST_F(BackgroundSyncManagerTest, RegistrationEqualsName) { +TEST_F(BackgroundSyncManagerTest, RegistrationEqualsTag) { BackgroundSyncManager::BackgroundSyncRegistration reg_1; BackgroundSyncManager::BackgroundSyncRegistration reg_2; EXPECT_TRUE(reg_1.Equals(reg_2)); - reg_2.name = "bar"; + reg_2.tag = "bar"; EXPECT_FALSE(reg_1.Equals(reg_2)); } @@ -676,7 +676,7 @@ TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) { BackgroundSyncManager::BackgroundSyncRegistration reg_1; // Set non-default values for each field. - reg_1.name = "foo"; + reg_1.tag = "foo"; reg_1.fire_once = !reg_1.fire_once; reg_1.min_period += 1; EXPECT_NE(NETWORK_STATE_ANY, reg_1.network_state); @@ -691,7 +691,7 @@ // disk. UseTestBackgroundSyncManager(); - EXPECT_TRUE(GetRegistration(reg_1.name)); + EXPECT_TRUE(GetRegistration(reg_1.tag)); EXPECT_TRUE(reg_1.Equals(callback_registration_)); }
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h index b778057..fe89e1c 100644 --- a/content/browser/bad_message.h +++ b/content/browser/bad_message.h
@@ -38,6 +38,7 @@ WC_INVALID_FRAME_SOURCE, RWHVM_UNEXPECTED_FRAME_TYPE, RFPH_DETACH, + DFH_BAD_EMBEDDER_MESSAGE, // Please add new elements here. The naming convention is abbreviated class // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the // reason.
diff --git a/content/browser/devtools/devtools_frontend_host_impl.cc b/content/browser/devtools/devtools_frontend_host_impl.cc index 6d3c6589..a25daee 100644 --- a/content/browser/devtools/devtools_frontend_host_impl.cc +++ b/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -4,6 +4,7 @@ #include "content/browser/devtools/devtools_frontend_host_impl.h" +#include "content/browser/bad_message.h" #include "content/common/devtools_messages.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_frame_host.h" @@ -31,6 +32,11 @@ DevToolsFrontendHostImpl::~DevToolsFrontendHostImpl() { } +void DevToolsFrontendHostImpl::BadMessageRecieved() { + bad_message::ReceivedBadMessage(web_contents()->GetRenderProcessHost(), + bad_message::DFH_BAD_EMBEDDER_MESSAGE); +} + bool DevToolsFrontendHostImpl::OnMessageReceived( const IPC::Message& message, RenderFrameHost* render_frame_host) {
diff --git a/content/browser/devtools/devtools_frontend_host_impl.h b/content/browser/devtools/devtools_frontend_host_impl.h index ee616e5..148bc2f6 100644 --- a/content/browser/devtools/devtools_frontend_host_impl.h +++ b/content/browser/devtools/devtools_frontend_host_impl.h
@@ -17,6 +17,8 @@ DevToolsFrontendHost::Delegate* delegate); ~DevToolsFrontendHostImpl() override; + void BadMessageRecieved() override; + private: // WebContentsObserver overrides. bool OnMessageReceived(const IPC::Message& message,
diff --git a/content/browser/devtools/protocol/color_picker.cc b/content/browser/devtools/protocol/color_picker.cc index 413fcfa..4afe2df 100644 --- a/content/browser/devtools/protocol/color_picker.cc +++ b/content/browser/devtools/protocol/color_picker.cc
@@ -33,7 +33,7 @@ ColorPicker::~ColorPicker() { } -void ColorPicker::SetRenderViewHost(RenderViewHostImpl* host) { +void ColorPicker::SetRenderWidgetHost(RenderWidgetHostImpl* host) { if (host_ == host) return;
diff --git a/content/browser/devtools/protocol/color_picker.h b/content/browser/devtools/protocol/color_picker.h index 3c6473a..e4de5257 100644 --- a/content/browser/devtools/protocol/color_picker.h +++ b/content/browser/devtools/protocol/color_picker.h
@@ -15,7 +15,7 @@ namespace content { -class RenderViewHostImpl; +class RenderWidgetHostImpl; namespace devtools { namespace page { @@ -27,7 +27,7 @@ explicit ColorPicker(ColorPickedCallback callback); virtual ~ColorPicker(); - void SetRenderViewHost(RenderViewHostImpl* host); + void SetRenderWidgetHost(RenderWidgetHostImpl* host); void SetEnabled(bool enabled); void OnSwapCompositorFrame(); @@ -44,7 +44,7 @@ int last_cursor_x_; int last_cursor_y_; RenderWidgetHost::MouseEventCallback mouse_event_callback_; - RenderViewHostImpl* host_; + RenderWidgetHostImpl* host_; base::WeakPtrFactory<ColorPicker> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ColorPicker);
diff --git a/content/browser/devtools/protocol/emulation_handler.cc b/content/browser/devtools/protocol/emulation_handler.cc index c57d899..184369b 100644 --- a/content/browser/devtools/protocol/emulation_handler.cc +++ b/content/browser/devtools/protocol/emulation_handler.cc
@@ -5,8 +5,9 @@ #include "content/browser/devtools/protocol/emulation_handler.h" #include "base/strings/string_number_conversions.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/geolocation/geolocation_service_context.h" -#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/view_messages.h" #include "content/public/common/url_constants.h" @@ -52,7 +53,7 @@ UpdateTouchEventEmulationState(); } -void EmulationHandler::SetRenderViewHost(RenderViewHostImpl* host) { +void EmulationHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { if (host_ == host) return; @@ -70,16 +71,11 @@ Response EmulationHandler::SetGeolocationOverride( double* latitude, double* longitude, double* accuracy) { - if (!host_) + if (!GetWebContents()) return Response::InternalError("Could not connect to view"); - WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( - WebContents::FromRenderViewHost(host_)); - if (!web_contents) - return Response::InternalError("No WebContents to override"); - GeolocationServiceContext* geolocation_context = - web_contents->GetGeolocationServiceContext(); + GetWebContents()->GetGeolocationServiceContext(); scoped_ptr<Geoposition> geoposition(new Geoposition()); if (latitude && longitude && accuracy) { geoposition->latitude = *latitude; @@ -97,16 +93,11 @@ } Response EmulationHandler::ClearGeolocationOverride() { - if (!host_) + if (!GetWebContents()) return Response::InternalError("Could not connect to view"); - WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( - WebContents::FromRenderViewHost(host_)); - if (!web_contents) - return Response::InternalError("No WebContents to override"); - GeolocationServiceContext* geolocation_context = - web_contents->GetGeolocationServiceContext(); + GetWebContents()->GetGeolocationServiceContext(); geolocation_context->ClearOverride(); return Response::OK(); } @@ -124,18 +115,11 @@ #if defined(OS_ANDROID) *result = false; #else - if (host_) { - if (WebContents* web_contents = WebContents::FromRenderViewHost(host_)) { - *result = web_contents->GetMainFrame()->GetRenderViewHost() == host_; + *result = true; #if defined(DEBUG_DEVTOOLS) - *result &= !web_contents->GetVisibleURL().SchemeIs(kChromeDevToolsScheme); + if (WebContentsImpl* web_contents = GetWebContents()) + *result &= !web_contents->GetVisibleURL().SchemeIs(kChromeDevToolsScheme); #endif // defined(DEBUG_DEVTOOLS) - } else { - *result = true; - } - } else { - *result = true; - } #endif // defined(OS_ANDROID) return Response::OK(); } @@ -194,28 +178,37 @@ return Response::OK(); } +WebContentsImpl* EmulationHandler::GetWebContents() { + return host_ ? + static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) : + nullptr; +} + void EmulationHandler::UpdateTouchEventEmulationState() { + RenderWidgetHostImpl* widget_host = + host_ ? host_->GetRenderWidgetHost() : nullptr; if (!host_) return; bool enabled = touch_emulation_enabled_ || page_handler_->screencast_enabled(); ui::GestureProviderConfigType config_type = TouchEmulationConfigurationToType(touch_emulation_configuration_); - host_->SetTouchEventEmulationEnabled(enabled, config_type); - WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( - WebContents::FromRenderViewHost(host_)); - if (web_contents) - web_contents->SetForceDisableOverscrollContent(enabled); + widget_host->SetTouchEventEmulationEnabled(enabled, config_type); + if (GetWebContents()) + GetWebContents()->SetForceDisableOverscrollContent(enabled); } void EmulationHandler::UpdateDeviceEmulationState() { + RenderWidgetHostImpl* widget_host = + host_ ? host_->GetRenderWidgetHost() : nullptr; if (!host_) return; if (device_emulation_enabled_) { - host_->Send(new ViewMsg_EnableDeviceEmulation( - host_->GetRoutingID(), device_emulation_params_)); + widget_host->Send(new ViewMsg_EnableDeviceEmulation( + widget_host->GetRoutingID(), device_emulation_params_)); } else { - host_->Send(new ViewMsg_DisableDeviceEmulation(host_->GetRoutingID())); + widget_host->Send(new ViewMsg_DisableDeviceEmulation( + widget_host->GetRoutingID())); } }
diff --git a/content/browser/devtools/protocol/emulation_handler.h b/content/browser/devtools/protocol/emulation_handler.h index 8f14b2f6..5303663c1 100644 --- a/content/browser/devtools/protocol/emulation_handler.h +++ b/content/browser/devtools/protocol/emulation_handler.h
@@ -11,7 +11,8 @@ namespace content { -class RenderViewHostImpl; +class RenderFrameHostImpl; +class WebContentsImpl; namespace devtools { @@ -29,7 +30,7 @@ // page::PageHandler::ScreencastListener implementation. void ScreencastEnabledChanged() override; - void SetRenderViewHost(RenderViewHostImpl* host); + void SetRenderFrameHost(RenderFrameHostImpl* host); void Detached(); Response SetGeolocationOverride(double* latitude, @@ -52,6 +53,7 @@ Response ClearDeviceMetricsOverride(); private: + WebContentsImpl* GetWebContents(); void UpdateTouchEventEmulationState(); void UpdateDeviceEmulationState(); @@ -62,7 +64,7 @@ blink::WebDeviceEmulationParams device_emulation_params_; page::PageHandler* page_handler_; - RenderViewHostImpl* host_; + RenderFrameHostImpl* host_; DISALLOW_COPY_AND_ASSIGN(EmulationHandler); };
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index d8ffcd5a..cc69f7d2 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -12,7 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/worker_pool.h" #include "content/browser/devtools/protocol/color_picker.h" -#include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/view_messages.h" @@ -20,6 +20,8 @@ #include "content/public/browser/javascript_dialog_manager.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/referrer.h" @@ -106,12 +108,29 @@ PageHandler::~PageHandler() { } -void PageHandler::SetRenderViewHost(RenderViewHostImpl* host) { +void PageHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { if (host_ == host) return; - color_picker_->SetRenderViewHost(host); + RenderWidgetHostImpl* widget_host = + host_ ? host_->GetRenderWidgetHost() : nullptr; + if (widget_host) { + registrar_.Remove( + this, + content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, + content::Source<RenderWidgetHost>(widget_host)); + } + host_ = host; + widget_host = host_ ? host_->GetRenderWidgetHost() : nullptr; + color_picker_->SetRenderWidgetHost(widget_host); + + if (widget_host) { + registrar_.Add( + this, + content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, + content::Source<RenderWidgetHost>(widget_host)); + } } void PageHandler::SetClient(scoped_ptr<Client> client) { @@ -134,9 +153,13 @@ color_picker_->OnSwapCompositorFrame(); } -void PageHandler::OnVisibilityChanged(bool visible) { +void PageHandler::Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { if (!screencast_enabled_) return; + DCHECK(type == content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED); + bool visible = *Details<bool>(details).ptr(); NotifyScreencastVisibility(visible); } @@ -173,12 +196,9 @@ Response PageHandler::Reload(const bool* ignoreCache, const std::string* script_to_evaluate_on_load, const std::string* script_preprocessor) { - if (!host_) - return Response::InternalError("Could not connect to view"); - - WebContents* web_contents = WebContents::FromRenderViewHost(host_); + WebContentsImpl* web_contents = GetWebContents(); if (!web_contents) - return Response::InternalError("No WebContents to reload"); + return Response::InternalError("Could not connect to view"); // Handle in browser only if it is crashed. if (!web_contents->IsCrashed()) @@ -194,12 +214,9 @@ if (!gurl.is_valid()) return Response::InternalError("Cannot navigate to invalid URL"); - if (!host_) - return Response::InternalError("Could not connect to view"); - - WebContents* web_contents = WebContents::FromRenderViewHost(host_); + WebContentsImpl* web_contents = GetWebContents(); if (!web_contents) - return Response::InternalError("No WebContents to navigate"); + return Response::InternalError("Could not connect to view"); web_contents->GetController() .LoadURL(gurl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); @@ -208,12 +225,9 @@ Response PageHandler::GetNavigationHistory(int* current_index, NavigationEntries* entries) { - if (!host_) - return Response::InternalError("Could not connect to view"); - - WebContents* web_contents = WebContents::FromRenderViewHost(host_); + WebContentsImpl* web_contents = GetWebContents(); if (!web_contents) - return Response::InternalError("No WebContents to navigate"); + return Response::InternalError("Could not connect to view"); NavigationController& controller = web_contents->GetController(); *current_index = controller.GetCurrentEntryIndex(); @@ -228,12 +242,9 @@ } Response PageHandler::NavigateToHistoryEntry(int entry_id) { - if (!host_) - return Response::InternalError("Could not connect to view"); - - WebContents* web_contents = WebContents::FromRenderViewHost(host_); + WebContentsImpl* web_contents = GetWebContents(); if (!web_contents) - return Response::InternalError("No WebContents to navigate"); + return Response::InternalError("Could not connect to view"); NavigationController& controller = web_contents->GetController(); for (int i = 0; i != controller.GetEntryCount(); ++i) { @@ -247,10 +258,10 @@ } Response PageHandler::CaptureScreenshot(DevToolsCommandId command_id) { - if (!host_ || !host_->GetView()) + if (!host_ || !host_->GetRenderWidgetHost()) return Response::InternalError("Could not connect to view"); - host_->GetSnapshotFromBrowser( + host_->GetRenderWidgetHost()->GetSnapshotFromBrowser( base::Bind(&PageHandler::ScreenshotCaptured, weak_factory_.GetWeakPtr(), command_id)); return Response::OK(); @@ -269,7 +280,9 @@ const int* quality, const int* max_width, const int* max_height) { - if (!host_) + RenderWidgetHostImpl* widget_host = + host_ ? host_->GetRenderWidgetHost() : nullptr; + if (!widget_host) return Response::InternalError("Could not connect to view"); screencast_enabled_ = true; @@ -280,13 +293,15 @@ screencast_max_width_ = max_width ? *max_width : -1; screencast_max_height_ = max_height ? *max_height : -1; - bool visible = !host_->is_hidden(); + bool visible = !widget_host->is_hidden(); NotifyScreencastVisibility(visible); if (visible) { - if (has_compositor_frame_metadata_) + if (has_compositor_frame_metadata_) { InnerSwapCompositorFrame(); - else - host_->Send(new ViewMsg_ForceRedraw(host_->GetRoutingID(), 0)); + } else { + widget_host->Send( + new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); + } } if (screencast_listener_) screencast_listener_->ScreencastEnabledChanged(); @@ -311,12 +326,9 @@ if (prompt_text) prompt_override = base::UTF8ToUTF16(*prompt_text); - if (!host_) - return Response::InternalError("Could not connect to view"); - - WebContents* web_contents = WebContents::FromRenderViewHost(host_); + WebContentsImpl* web_contents = GetWebContents(); if (!web_contents) - return Response::InternalError("No JavaScript dialog to handle"); + return Response::InternalError("Could not connect to view"); JavaScriptDialogManager* manager = web_contents->GetDelegate()->GetJavaScriptDialogManager(web_contents); @@ -341,6 +353,12 @@ return Response::OK(); } +WebContentsImpl* PageHandler::GetWebContents() { + return host_ ? + static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) : + nullptr; +} + void PageHandler::NotifyScreencastVisibility(bool visible) { if (visible) capture_retry_count_ = kCaptureRetryLimit;
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index 5749439..fff0cda 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -11,20 +11,23 @@ #include "base/time/time.h" #include "cc/output/compositor_frame_metadata.h" #include "content/browser/devtools/protocol/devtools_protocol_handler.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" #include "content/public/browser/readback_types.h" class SkBitmap; namespace content { -class RenderViewHostImpl; +class RenderFrameHostImpl; +class WebContentsImpl; namespace devtools { namespace page { class ColorPicker; -class PageHandler { +class PageHandler : public NotificationObserver { public: typedef DevToolsProtocolClient::Response Response; @@ -35,13 +38,12 @@ }; PageHandler(); - virtual ~PageHandler(); + ~PageHandler() override; - void SetRenderViewHost(RenderViewHostImpl* host); + void SetRenderFrameHost(RenderFrameHostImpl* host); void SetClient(scoped_ptr<Client> client); void Detached(); void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata); - void OnVisibilityChanged(bool visible); void DidAttachInterstitialPage(); void DidDetachInterstitialPage(); void SetScreencastListener(ScreencastListener* listener); @@ -80,6 +82,7 @@ Response SetColorPickerEnabled(bool enabled); private: + WebContentsImpl* GetWebContents(); void NotifyScreencastVisibility(bool visible); void InnerSwapCompositorFrame(); void ScreencastFrameCaptured(const cc::CompositorFrameMetadata& metadata, @@ -96,6 +99,11 @@ void OnColorPicked(int r, int g, int b, int a); + // NotificationObserver overrides. + void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) override; + bool enabled_; bool screencast_enabled_; @@ -113,9 +121,10 @@ scoped_ptr<ColorPicker> color_picker_; - RenderViewHostImpl* host_; + RenderFrameHostImpl* host_; scoped_ptr<Client> client_; ScreencastListener* screencast_listener_; + NotificationRegistrar registrar_; base::WeakPtrFactory<PageHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(PageHandler);
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 1fa9c79..ba5757e6 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -28,8 +28,6 @@ #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" #include "content/public/browser/render_widget_host_iterator.h" #include "content/public/browser/web_contents_delegate.h" @@ -141,26 +139,32 @@ input_handler_(new devtools::input::InputHandler()), inspector_handler_(new devtools::inspector::InspectorHandler()), network_handler_(new devtools::network::NetworkHandler()), - page_handler_(new devtools::page::PageHandler()), + page_handler_(nullptr), power_handler_(new devtools::power::PowerHandler()), service_worker_handler_( new devtools::service_worker::ServiceWorkerHandler()), tracing_handler_(new devtools::tracing::TracingHandler( devtools::tracing::TracingHandler::Renderer)), - emulation_handler_(new devtools::emulation::EmulationHandler( - page_handler_.get())), + emulation_handler_(nullptr), frame_trace_recorder_(new DevToolsFrameTraceRecorder()), reattaching_(false) { DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher(); dispatcher->SetDOMHandler(dom_handler_.get()); - dispatcher->SetEmulationHandler(emulation_handler_.get()); dispatcher->SetInputHandler(input_handler_.get()); dispatcher->SetInspectorHandler(inspector_handler_.get()); dispatcher->SetNetworkHandler(network_handler_.get()); - dispatcher->SetPageHandler(page_handler_.get()); dispatcher->SetPowerHandler(power_handler_.get()); dispatcher->SetServiceWorkerHandler(service_worker_handler_.get()); dispatcher->SetTracingHandler(tracing_handler_.get()); + + if (!rfh->GetParent()) { + page_handler_.reset(new devtools::page::PageHandler()); + emulation_handler_.reset( + new devtools::emulation::EmulationHandler(page_handler_.get())); + dispatcher->SetPageHandler(page_handler_.get()); + dispatcher->SetEmulationHandler(emulation_handler_.get()); + } + SetRenderFrameHost(rfh); g_instances.Get().push_back(this); AddRef(); // Balanced in RenderFrameHostDestroyed. @@ -204,12 +208,8 @@ PowerSaveBlocker::Create( PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, PowerSaveBlocker::kReasonOther, "DevTools").release())); - RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( - render_frame_host_->GetRenderViewHost()); - if (rvh->GetView()) { - power_save_blocker_.get()-> - InitDisplaySleepBlocker(rvh->GetView()->GetNativeView()); - } + power_save_blocker_->InitDisplaySleepBlocker( + WebContents::FromRenderFrameHost(render_frame_host_)); #endif } @@ -217,8 +217,10 @@ #if defined(OS_ANDROID) power_save_blocker_.reset(); #endif - emulation_handler_->Detached(); - page_handler_->Detached(); + if (emulation_handler_) + emulation_handler_->Detached(); + if (page_handler_) + page_handler_->Detached(); power_handler_->Detached(); service_worker_handler_->Detached(); tracing_handler_->Detached(); @@ -365,7 +367,8 @@ } void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() { - page_handler_->DidAttachInterstitialPage(); + if (page_handler_) + page_handler_->DidAttachInterstitialPage(); if (!render_frame_host_) return; @@ -380,7 +383,8 @@ } void RenderFrameDevToolsAgentHost::DidDetachInterstitialPage() { - page_handler_->DidDetachInterstitialPage(); + if (page_handler_) + page_handler_->DidDetachInterstitialPage(); } void RenderFrameDevToolsAgentHost::TitleWasSet( @@ -400,15 +404,6 @@ service_worker_handler_->UpdateHosts(); } -void RenderFrameDevToolsAgentHost::Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) { - bool visible = *Details<bool>(details).ptr(); - page_handler_->OnVisibilityChanged(visible); - } -} - void RenderFrameDevToolsAgentHost::SetRenderFrameHost(RenderFrameHost* rfh) { DCHECK(ShouldCreateDevToolsFor(rfh)); DCHECK(!render_frame_host_); @@ -418,32 +413,26 @@ RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( rfh->GetRenderViewHost()); dom_handler_->SetRenderFrameHost(render_frame_host_); - emulation_handler_->SetRenderViewHost(rvh); input_handler_->SetRenderViewHost(rvh); network_handler_->SetRenderFrameHost(render_frame_host_); - page_handler_->SetRenderViewHost(rvh); service_worker_handler_->SetRenderFrameHost(render_frame_host_); - registrar_.Add( - this, - content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, - content::Source<RenderWidgetHost>(rvh)); + if (emulation_handler_) + emulation_handler_->SetRenderFrameHost(render_frame_host_); + if (page_handler_) + page_handler_->SetRenderFrameHost(render_frame_host_); } void RenderFrameDevToolsAgentHost::ClearRenderFrameHost() { DCHECK(render_frame_host_); - RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( - render_frame_host_->GetRenderViewHost()); - registrar_.Remove( - this, - content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, - content::Source<RenderWidgetHost>(rvh)); render_frame_host_ = nullptr; dom_handler_->SetRenderFrameHost(nullptr); - emulation_handler_->SetRenderViewHost(nullptr); + if (emulation_handler_) + emulation_handler_->SetRenderFrameHost(nullptr); input_handler_->SetRenderViewHost(nullptr); network_handler_->SetRenderFrameHost(nullptr); - page_handler_->SetRenderViewHost(nullptr); + if (page_handler_) + page_handler_->SetRenderFrameHost(nullptr); service_worker_handler_->SetRenderFrameHost(nullptr); } @@ -512,7 +501,8 @@ ViewHostMsg_SwapCompositorFrame::Param param; if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m)) return; - page_handler_->OnSwapCompositorFrame(get<1>(param).metadata); + if (page_handler_) + page_handler_->OnSwapCompositorFrame(get<1>(param).metadata); frame_trace_recorder_->OnSwapCompositorFrame( render_frame_host_, get<1>(param).metadata); } @@ -521,7 +511,8 @@ const cc::CompositorFrameMetadata& frame_metadata) { if (!render_frame_host_) return; - page_handler_->OnSwapCompositorFrame(frame_metadata); + if (page_handler_) + page_handler_->OnSwapCompositorFrame(frame_metadata); frame_trace_recorder_->OnSwapCompositorFrame( render_frame_host_, frame_metadata); }
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index 599962d..1808211 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -12,8 +12,6 @@ #include "base/memory/scoped_ptr.h" #include "content/browser/devtools/ipc_devtools_agent_host.h" #include "content/common/content_export.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_observer.h" namespace cc { @@ -45,8 +43,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost : public IPCDevToolsAgentHost, - private WebContentsObserver, - public NotificationObserver { + private WebContentsObserver { public: static void AddAllAgentHosts(DevToolsAgentHost::List* result); @@ -104,11 +101,6 @@ const GURL& url, ui::PageTransition transition_type) override; - // NotificationObserver overrides: - void Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) override; - void DisconnectRenderFrameHost(); void ConnectRenderFrameHost(RenderFrameHost* rvh); void ReattachToRenderFrameHost(RenderFrameHost* rvh); @@ -145,7 +137,6 @@ #if defined(OS_ANDROID) scoped_ptr<PowerSaveBlockerImpl> power_save_blocker_; #endif - NotificationRegistrar registrar_; bool reattaching_; DISALLOW_COPY_AND_ASSIGN(RenderFrameDevToolsAgentHost);
diff --git a/content/browser/devtools/service_worker_devtools_manager.cc b/content/browser/devtools/service_worker_devtools_manager.cc index 9b639c6..a423066 100644 --- a/content/browser/devtools/service_worker_devtools_manager.cc +++ b/content/browser/devtools/service_worker_devtools_manager.cc
@@ -91,7 +91,7 @@ workers_[id] = agent_host; DevToolsManager::GetInstance()->AgentHostChanged(agent_host); - return it->second->IsAttached(); + return agent_host->IsAttached(); } void ServiceWorkerDevToolsManager::WorkerReadyForInspection(
diff --git a/content/browser/frame_host/render_frame_host_delegate.cc b/content/browser/frame_host/render_frame_host_delegate.cc index 4c81621..ff4aba61 100644 --- a/content/browser/frame_host/render_frame_host_delegate.cc +++ b/content/browser/frame_host/render_frame_host_delegate.cc
@@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/strings/string16.h" #include "content/browser/frame_host/render_frame_host_delegate.h" +#include "ipc/ipc_message.h" #include "ui/gfx/native_widget_types.h" #include "url/gurl.h" @@ -69,6 +70,17 @@ return NULL; } +bool RenderFrameHostDelegate::ShouldRouteMessageEvent( + RenderFrameHost* target_rfh, + SiteInstance* source_site_instance) const { + return false; +} + +int RenderFrameHostDelegate::EnsureOpenerRenderViewsExist( + RenderFrameHost* source_rfh) { + return MSG_ROUTING_NONE; +} + #if defined(OS_WIN) gfx::NativeViewAccessible RenderFrameHostDelegate::GetParentNativeViewAccessible() {
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h index 56b56347..f0e9fbd 100644 --- a/content/browser/frame_host/render_frame_host_delegate.h +++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -11,6 +11,7 @@ #include "base/i18n/rtl.h" #include "content/common/content_export.h" #include "content/common/frame_message_enums.h" +#include "content/public/browser/site_instance.h" #include "content/public/common/javascript_message_type.h" #include "content/public/common/media_stream_request.h" #include "net/http/http_response_headers.h" @@ -168,6 +169,26 @@ // Notification that the frame wants to go out of fullscreen mode. virtual void ExitFullscreenMode() {} + // Let the delegate decide whether postMessage should be delivered to + // |target_rfh| from a source frame in the given SiteInstance. This defaults + // to false and overrides the RenderFrameHost's decision if true. + virtual bool ShouldRouteMessageEvent( + RenderFrameHost* target_rfh, + SiteInstance* source_site_instance) const; + + // Ensure that |source_rfh| has swapped-out RenderViews and proxies for + // itself and for each frame on its opener chain in the current frame's + // SiteInstance. Returns the routing ID of the swapped-out RenderView + // corresponding to |source_rfh|. + // + // TODO(alexmos): This method will be removed once opener tracking and + // CreateOpenerRenderViews moves out of WebContents and into lower layers, as + // part of https://crbug.com/225940. Currently, this method temporarily + // supports cross-process postMessage in non-site-per-process mode, where we + // need to create any missing proxies for the message's source frame and its + // opener chain on demand. + virtual int EnsureOpenerRenderViewsExist(RenderFrameHost* source_rfh); + #if defined(OS_WIN) // Returns the frame's parent's NativeViewAccessible. virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index 827b034c..d027c06 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -455,45 +455,39 @@ void RenderFrameHostManager::CommitPendingIfNecessary( RenderFrameHostImpl* render_frame_host, bool was_caused_by_user_gesture) { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableBrowserSideNavigation)) { - if (render_frame_host == speculative_render_frame_host_.get()) { - CommitPending(); - } else if (render_frame_host == render_frame_host_.get()) { - // TODO(carlosk): this code doesn't properly handle in-page navigation or - // interwoven navigation requests. - DCHECK(!speculative_render_frame_host_); - } else { - // No one else should be sending us a DidNavigate in this state. - DCHECK(false); - } - DCHECK(!speculative_render_frame_host_); - return; - } - + // Note: In PlzNavigate |cross_navigation_pending_| being false means there is + // *no* speculative RenderFrameHost set. if (!cross_navigation_pending_) { + DCHECK(!speculative_render_frame_host_); DCHECK(!pending_render_frame_host_); + DCHECK_IMPLIES(should_reuse_web_ui_, web_ui_); // We should only hear this from our current renderer. DCHECK_EQ(render_frame_host_, render_frame_host); // Even when there is no pending RVH, there may be a pending Web UI. - if (pending_web_ui()) + if (pending_web_ui() || speculative_web_ui_) CommitPending(); return; } - if (render_frame_host == pending_render_frame_host_) { + if (render_frame_host == pending_render_frame_host_ || + render_frame_host == speculative_render_frame_host_) { // The pending cross-site navigation completed, so show the renderer. CommitPending(); } else if (render_frame_host == render_frame_host_) { - if (was_caused_by_user_gesture) { - // A navigation in the original page has taken place. Cancel the pending - // one. Only do it for user gesture originated navigations to prevent - // page doing any shenanigans to prevent user from navigating. - // See https://code.google.com/p/chromium/issues/detail?id=75195 - CancelPending(); - cross_navigation_pending_ = false; + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation)) { + CleanUpNavigation(); + } else { + if (was_caused_by_user_gesture) { + // A navigation in the original page has taken place. Cancel the + // pending one. Only do it for user gesture originated navigations to + // prevent page doing any shenanigans to prevent user from navigating. + // See https://code.google.com/p/chromium/issues/detail?id=75195 + CancelPending(); + cross_navigation_pending_ = false; + } } } else { // No one else should be sending us DidNavigate in this state. @@ -1680,26 +1674,27 @@ // this triggers won't be able to figure out what's going on. bool will_focus_location_bar = delegate_->FocusLocationBarByDefault(); - if (!browser_side_navigation) { - DCHECK(!speculative_web_ui_); - // Next commit the Web UI, if any. Either replace |web_ui_| with - // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or - // leave |web_ui_| as is if reusing it. - DCHECK(!(pending_web_ui_.get() && pending_and_current_web_ui_.get())); - if (pending_web_ui_) { - web_ui_.reset(pending_web_ui_.release()); - } else if (!pending_and_current_web_ui_.get()) { - web_ui_.reset(); + // Next commit the Web UI, if any. Either replace |web_ui_| with + // |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or + // leave |web_ui_| as is if reusing it. + DCHECK(!(pending_web_ui_ && pending_and_current_web_ui_)); + if (pending_web_ui_ || speculative_web_ui_) { + DCHECK(!should_reuse_web_ui_); + web_ui_.reset(browser_side_navigation ? speculative_web_ui_.release() + : pending_web_ui_.release()); + } else if (pending_and_current_web_ui_ || should_reuse_web_ui_) { + if (browser_side_navigation) { + DCHECK(web_ui_); + should_reuse_web_ui_ = false; } else { DCHECK_EQ(pending_and_current_web_ui_.get(), web_ui_.get()); pending_and_current_web_ui_.reset(); } } else { - // PlzNavigate - if (!should_reuse_web_ui_) - web_ui_.reset(speculative_web_ui_.release()); - DCHECK(!speculative_web_ui_); + web_ui_.reset(); } + DCHECK(!speculative_web_ui_); + DCHECK(!should_reuse_web_ui_); // It's possible for the pending_render_frame_host_ to be nullptr when we // aren't crossing process boundaries. If so, we just needed to handle the Web
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 2f0ece60f..d1c0c74 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -1076,6 +1076,41 @@ manager2->DidNavigateFrame(host2, true); } +// Tests that a WebUI is correctly reused between chrome:// pages. +TEST_F(RenderFrameHostManagerTest, WebUIWasReused) { + set_should_create_webui(true); + + // Navigate to a WebUI page. + const GURL kUrl1("chrome://foo"); + contents()->NavigateAndCommit(kUrl1); + RenderFrameHostManager* manager = + main_test_rfh()->frame_tree_node()->render_manager(); + WebUIImpl* web_ui = manager->web_ui(); + EXPECT_TRUE(web_ui); + + // Navigate to another WebUI page which should be same-site and keep the + // current WebUI. + const GURL kUrl2("chrome://foo/bar"); + contents()->NavigateAndCommit(kUrl2); + EXPECT_EQ(web_ui, manager->web_ui()); +} + +// Tests that a WebUI is correctly cleaned up when navigating from a chrome:// +// page to a non-chrome:// page. +TEST_F(RenderFrameHostManagerTest, WebUIWasCleared) { + set_should_create_webui(true); + + // Navigate to a WebUI page. + const GURL kUrl1("chrome://foo"); + contents()->NavigateAndCommit(kUrl1); + EXPECT_TRUE(main_test_rfh()->frame_tree_node()->render_manager()->web_ui()); + + // Navigate to a non-WebUI page. + const GURL kUrl2("http://www.google.com"); + contents()->NavigateAndCommit(kUrl2); + EXPECT_FALSE(main_test_rfh()->frame_tree_node()->render_manager()->web_ui()); +} + // Tests that we don't end up in an inconsistent state if a page does a back and // then reload. http://crbug.com/51680 // Also tests that only user-gesture navigations can interrupt cross-process
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc index cc6addf3..fe62776 100644 --- a/content/browser/frame_host/render_frame_proxy_host.cc +++ b/content/browser/frame_host/render_frame_proxy_host.cc
@@ -9,8 +9,10 @@ #include "content/browser/frame_host/cross_process_frame_connector.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_widget_host_view_child_frame.h" +#include "content/browser/message_port_message_filter.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/site_instance_impl.h" @@ -119,6 +121,7 @@ IPC_BEGIN_MESSAGE_MAP(RenderFrameProxyHost, msg) IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach) IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL) + IPC_MESSAGE_HANDLER(FrameHostMsg_RouteMessageEvent, OnRouteMessageEvent) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -178,4 +181,85 @@ frame_tree_node_->current_frame_host()->OpenURL(params, site_instance_.get()); } +void RenderFrameProxyHost::OnRouteMessageEvent( + const FrameMsg_PostMessage_Params& params) { + RenderFrameHostImpl* target_rfh = frame_tree_node()->current_frame_host(); + + // Only deliver the message if the request came from a RenderFrameHost in the + // same BrowsingInstance or if this WebContents is dedicated to a browser + // plugin guest. + // + // TODO(alexmos, lazyboy): The check for browser plugin guest currently + // requires going through the delegate. It should be refactored and + // performed here once OOPIF support in <webview> is further along. + SiteInstance* target_site_instance = target_rfh->GetSiteInstance(); + if (!target_site_instance->IsRelatedSiteInstance(GetSiteInstance()) && + !target_rfh->delegate()->ShouldRouteMessageEvent(target_rfh, + GetSiteInstance())) + return; + + FrameMsg_PostMessage_Params new_params(params); + + // If there is a source_routing_id, translate it to the routing ID of the + // equivalent RenderFrameProxyHost in the target process. + if (new_params.source_routing_id != MSG_ROUTING_NONE) { + RenderFrameHostImpl* source_rfh = RenderFrameHostImpl::FromID( + GetProcess()->GetID(), new_params.source_routing_id); + if (!source_rfh) { + new_params.source_routing_id = MSG_ROUTING_NONE; + } else { + // Ensure that we have a swapped-out RVH and proxy for the source frame. + // If it doesn't exist, create it on demand and also create its opener + // chain, since those will also be accessible to the target page. + // + // TODO(alexmos): This currently only works for top-level frames and + // won't create the right proxy if the message source is a subframe on a + // cross-process tab. This will be cleaned up as part of moving opener + // tracking to FrameTreeNode (https://crbug.com/225940). For now, if the + // message is sent from a subframe on a cross-process tab, set the source + // routing ID to the main frame of the source tab, which matches legacy + // postMessage behavior prior to --site-per-process. + int source_view_routing_id = + target_rfh->delegate()->EnsureOpenerRenderViewsExist(source_rfh); + + RenderFrameProxyHost* source_proxy_in_target_site_instance = + source_rfh->frame_tree_node() + ->render_manager() + ->GetRenderFrameProxyHost(target_rfh->GetSiteInstance()); + if (source_proxy_in_target_site_instance) { + new_params.source_routing_id = + source_proxy_in_target_site_instance->GetRoutingID(); + } else if (source_view_routing_id != MSG_ROUTING_NONE) { + RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( + target_rfh->GetProcess()->GetID(), source_view_routing_id); + CHECK(source_rvh); + new_params.source_routing_id = source_rvh->main_frame_routing_id(); + } else { + new_params.source_routing_id = MSG_ROUTING_NONE; + } + } + } + + if (!params.message_ports.empty()) { + // Updating the message port information has to be done in the IO thread; + // MessagePortMessageFilter::RouteMessageEventWithMessagePorts will send + // FrameMsg_PostMessageEvent after it's done. Note that a trivial solution + // would've been to post a task on the IO thread to do the IO-thread-bound + // work, and make that post a task back to WebContentsImpl in the UI + // thread. But we cannot do that, since there's nothing to guarantee that + // WebContentsImpl stays alive during the round trip. + scoped_refptr<MessagePortMessageFilter> message_port_message_filter( + static_cast<RenderProcessHostImpl*>(target_rfh->GetProcess()) + ->message_port_message_filter()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&MessagePortMessageFilter::RouteMessageEventWithMessagePorts, + message_port_message_filter, target_rfh->GetRoutingID(), + new_params)); + } else { + target_rfh->Send( + new FrameMsg_PostMessageEvent(target_rfh->GetRoutingID(), new_params)); + } +} + } // namespace content
diff --git a/content/browser/frame_host/render_frame_proxy_host.h b/content/browser/frame_host/render_frame_proxy_host.h index adfa6a0..9594f75 100644 --- a/content/browser/frame_host/render_frame_proxy_host.h +++ b/content/browser/frame_host/render_frame_proxy_host.h
@@ -11,6 +11,8 @@ #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" +struct FrameMsg_PostMessage_Params; + namespace content { class CrossProcessFrameConnector; @@ -117,6 +119,7 @@ // IPC Message handlers. void OnDetach(); void OnOpenURL(const FrameHostMsg_OpenURL_Params& params); + void OnRouteMessageEvent(const FrameMsg_PostMessage_Params& params); // This RenderFrameProxyHost's routing id. int routing_id_;
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc index 3a013df0..6a4985f7 100644 --- a/content/browser/gpu/gpu_internals_ui.cc +++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -154,6 +154,8 @@ gpu_info.pixel_shader_version)); basic_info->Append(NewDescriptionValuePair("Vertex shader version", gpu_info.vertex_shader_version)); + basic_info->Append(NewDescriptionValuePair("Max. MSAA samples", + gpu_info.max_msaa_samples)); basic_info->Append(NewDescriptionValuePair("Machine model name", gpu_info.machine_model_name)); basic_info->Append(NewDescriptionValuePair("Machine model version",
diff --git a/content/browser/media/capture/content_video_capture_device_core.cc b/content/browser/media/capture/content_video_capture_device_core.cc index 5030f6d..3c507c6f 100644 --- a/content/browser/media/capture/content_video_capture_device_core.cc +++ b/content/browser/media/capture/content_video_capture_device_core.cc
@@ -67,10 +67,6 @@ if (!client_) return false; // Capture is stopped. - const media::VideoFrame::Format video_frame_format = - params_.requested_format.pixel_format == media::PIXEL_FORMAT_TEXTURE ? - media::VideoFrame::NATIVE_TEXTURE : media::VideoFrame::I420; - if (capture_size_.IsEmpty()) capture_size_ = max_frame_size(); const gfx::Size visible_size = capture_size_; @@ -80,7 +76,8 @@ (visible_size.height() + 15) & ~15); scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer = - client_->ReserveOutputBuffer(video_frame_format, coded_size); + client_->ReserveOutputBuffer(params_.requested_format.pixel_format, + coded_size); const bool should_capture = oracle_.ObserveEventAndDecideCapture(event, damage_rect, event_time); const char* event_name = @@ -120,9 +117,9 @@ "trigger", event_name); // NATIVE_TEXTURE frames wrap a texture mailbox, which we don't have at the // moment. We do not construct those frames. - if (video_frame_format != media::VideoFrame::NATIVE_TEXTURE) { + if (params_.requested_format.pixel_format != media::PIXEL_FORMAT_TEXTURE) { *storage = media::VideoFrame::WrapExternalPackedMemory( - video_frame_format, + media::VideoFrame::I420, coded_size, gfx::Rect(visible_size), visible_size,
diff --git a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc index c240356..4c69a57 100644 --- a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc +++ b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -52,7 +52,7 @@ int clockwise_rotation, const base::TimeTicks& timestamp)); MOCK_METHOD2(ReserveOutputBuffer, - scoped_refptr<Buffer>(media::VideoFrame::Format format, + scoped_refptr<Buffer>(media::VideoPixelFormat format, const gfx::Size& dimensions)); MOCK_METHOD3(OnIncomingCapturedVideoFrame, void(const scoped_refptr<Buffer>& buffer,
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc index 48be8f1..1a874f4 100644 --- a/content/browser/media/capture/desktop_capture_device_unittest.cc +++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -70,7 +70,7 @@ int clockwise_rotation, const base::TimeTicks& timestamp)); MOCK_METHOD2(ReserveOutputBuffer, - scoped_refptr<Buffer>(media::VideoFrame::Format format, + scoped_refptr<Buffer>(media::VideoPixelFormat format, const gfx::Size& dimensions)); MOCK_METHOD3(OnIncomingCapturedVideoFrame, void(const scoped_refptr<Buffer>& buffer,
diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc index 10d8c06..8b24ed79 100644 --- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc +++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -336,14 +336,12 @@ } scoped_refptr<media::VideoCaptureDevice::Client::Buffer> ReserveOutputBuffer( - media::VideoFrame::Format format, + media::VideoPixelFormat format, const gfx::Size& dimensions) override { - CHECK_EQ(format, media::VideoFrame::I420); - const size_t frame_bytes = - media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions); + CHECK_EQ(format, media::PIXEL_FORMAT_I420); int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; // Ignored. - int buffer_id = - buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); + int buffer_id = buffer_pool_->ReserveForProducer(format, dimensions, + &buffer_id_to_drop); if (buffer_id == VideoCaptureBufferPool::kInvalidId) return NULL; void* data;
diff --git a/content/browser/message_port_message_filter.cc b/content/browser/message_port_message_filter.cc index 6dc44b6..5ff0319d 100644 --- a/content/browser/message_port_message_filter.cc +++ b/content/browser/message_port_message_filter.cc
@@ -5,8 +5,8 @@ #include "content/browser/message_port_message_filter.h" #include "content/browser/message_port_service.h" +#include "content/common/frame_messages.h" #include "content/common/message_port_messages.h" -#include "content/common/view_messages.h" namespace content { @@ -95,14 +95,13 @@ void MessagePortMessageFilter::RouteMessageEventWithMessagePorts( int routing_id, - const ViewMsg_PostMessage_Params& params) { - ViewMsg_PostMessage_Params new_params(params); + const FrameMsg_PostMessage_Params& params) { + FrameMsg_PostMessage_Params new_params(params); UpdateMessagePortsWithNewRoutes(params.message_ports, &new_params.new_routing_ids); - Send(new ViewMsg_PostMessageEvent(routing_id, new_params)); + Send(new FrameMsg_PostMessageEvent(routing_id, new_params)); } - void MessagePortMessageFilter::OnCreateMessagePort(int *route_id, int* message_port_id) { *route_id = next_routing_id_.Run();
diff --git a/content/browser/message_port_message_filter.h b/content/browser/message_port_message_filter.h index e71a2356..be6bfde 100644 --- a/content/browser/message_port_message_filter.h +++ b/content/browser/message_port_message_filter.h
@@ -15,7 +15,7 @@ #undef SendMessage #endif -struct ViewMsg_PostMessage_Params; +struct FrameMsg_PostMessage_Params; namespace content { struct TransferredMessagePort; @@ -54,7 +54,7 @@ void RouteMessageEventWithMessagePorts( int routing_id, - const ViewMsg_PostMessage_Params& params); + const FrameMsg_PostMessage_Params& params); protected: // This is protected, so we can define sub classes for testing.
diff --git a/content/browser/message_port_provider.cc b/content/browser/message_port_provider.cc index eb932d9f..ddd19ad 100644 --- a/content/browser/message_port_provider.cc +++ b/content/browser/message_port_provider.cc
@@ -11,7 +11,7 @@ #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" -#include "content/common/view_messages.h" +#include "content/common/frame_messages.h" #include "content/public/browser/message_port_delegate.h" namespace content { @@ -25,12 +25,17 @@ const std::vector<TransferredMessagePort>& ports) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ViewMsg_PostMessage_Params params; + FrameMsg_PostMessage_Params params; params.is_data_raw_string = true; params.data = data; // Blink requires a source frame to transfer ports. This is why a // source routing id is set here. See WebDOMMessageEvent::initMessageEvent() - params.source_routing_id = web_contents->GetRoutingID(); + // TODO(alexmos, sgurun): Clean this up once crbug.com/473258 is fixed. + // Once message ports can work with a null source frame, + // source_view_routing_id can be removed, and this can just pass in + // MSG_ROUTING_NONE for the source frame. + params.source_view_routing_id = web_contents->GetRoutingID(); + params.source_routing_id = MSG_ROUTING_NONE; params.source_origin = source_origin; params.target_origin = target_origin; params.message_ports = ports; @@ -41,7 +46,7 @@ BrowserThread::IO, FROM_HERE, base::Bind(&MessagePortMessageFilter::RouteMessageEventWithMessagePorts, rph->message_port_message_filter(), - web_contents->GetRoutingID(), params)); + web_contents->GetMainFrame()->GetRoutingID(), params)); } // static
diff --git a/content/browser/net/sqlite_persistent_cookie_store.cc b/content/browser/net/sqlite_persistent_cookie_store.cc index 913b244..c4c6a141 100644 --- a/content/browser/net/sqlite_persistent_cookie_store.cc +++ b/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -951,7 +951,7 @@ meta_table_.Reset(); db_.reset(new sql::Connection); - if (!base::DeleteFile(path_, false) || + if (!sql::Connection::Delete(path_) || !db_->Open(path_) || !meta_table_.Init( db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
diff --git a/content/browser/power_save_blocker_android.cc b/content/browser/power_save_blocker_android.cc index 1e91625..20ea63cc 100644 --- a/content/browser/power_save_blocker_android.cc +++ b/content/browser/power_save_blocker_android.cc
@@ -2,30 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/power_save_blocker_android.h" - #include "base/android/jni_android.h" -#include "base/android/jni_weak_ref.h" #include "base/logging.h" +#include "content/browser/android/content_view_core_impl.h" #include "content/browser/power_save_blocker_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/android/content_view_core.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents_observer.h" #include "jni/PowerSaveBlocker_jni.h" #include "ui/android/view_android.h" -using base::android::AttachCurrentThread; -using base::android::ScopedJavaLocalRef; -using gfx::NativeView; - namespace content { +using base::android::AttachCurrentThread; + class PowerSaveBlockerImpl::Delegate - : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> { + : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate>, + public WebContentsObserver { public: - explicit Delegate(NativeView view_android) { - j_view_android_ = JavaObjectWeakGlobalRef( - AttachCurrentThread(), view_android->GetJavaObject().obj()); - } + explicit Delegate(WebContents* web_contents); // Does the actual work to apply or remove the desired power save block. void ApplyBlock(); @@ -33,27 +29,61 @@ private: friend class base::RefCountedThreadSafe<Delegate>; - ~Delegate() {} + ~Delegate() override; - JavaObjectWeakGlobalRef j_view_android_; + base::android::ScopedJavaLocalRef<jobject> GetContentViewCore(); + + base::android::ScopedJavaGlobalRef<jobject> java_power_save_blocker_; DISALLOW_COPY_AND_ASSIGN(Delegate); }; +PowerSaveBlockerImpl::Delegate::Delegate(WebContents* web_contents) + : WebContentsObserver(web_contents) { + JNIEnv* env = AttachCurrentThread(); + java_power_save_blocker_.Reset(Java_PowerSaveBlocker_create(env)); +} + +PowerSaveBlockerImpl::Delegate::~Delegate() { +} + void PowerSaveBlockerImpl::Delegate::ApplyBlock() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::android::ScopedJavaLocalRef<jobject> java_content_view_core = + GetContentViewCore(); + if (java_content_view_core.is_null()) + return; + + ScopedJavaLocalRef<jobject> obj(java_power_save_blocker_); JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> j_object = j_view_android_.get(env); - if (j_object.obj()) - Java_PowerSaveBlocker_applyBlock(env, j_object.obj()); + Java_PowerSaveBlocker_applyBlock(env, obj.obj(), + java_content_view_core.obj()); } void PowerSaveBlockerImpl::Delegate::RemoveBlock() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + base::android::ScopedJavaLocalRef<jobject> java_content_view_core = + GetContentViewCore(); + if (java_content_view_core.is_null()) + return; + + ScopedJavaLocalRef<jobject> obj(java_power_save_blocker_); JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> j_object = j_view_android_.get(env); - if (j_object.obj()) - Java_PowerSaveBlocker_removeBlock(env, j_object.obj()); + Java_PowerSaveBlocker_removeBlock(env, obj.obj(), + java_content_view_core.obj()); +} + +base::android::ScopedJavaLocalRef<jobject> +PowerSaveBlockerImpl::Delegate::GetContentViewCore() { + if (!web_contents()) + return base::android::ScopedJavaLocalRef<jobject>(); + + ContentViewCoreImpl* content_view_core_impl = + ContentViewCoreImpl::FromWebContents(web_contents()); + if (!content_view_core_impl) + return base::android::ScopedJavaLocalRef<jobject>(); + + return content_view_core_impl->GetJavaObject(); } PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type, @@ -70,15 +100,13 @@ } } -void PowerSaveBlockerImpl::InitDisplaySleepBlocker(NativeView view_android) { - if (!view_android) +void PowerSaveBlockerImpl::InitDisplaySleepBlocker(WebContents* web_contents) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!web_contents) return; - delegate_ = new Delegate(view_android); - // This may be called on any thread. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&Delegate::ApplyBlock, delegate_)); + delegate_ = new Delegate(web_contents); + delegate_->ApplyBlock(); } bool RegisterPowerSaveBlocker(JNIEnv* env) {
diff --git a/content/browser/power_save_blocker_impl.h b/content/browser/power_save_blocker_impl.h index 7ba0b542..a304226 100644 --- a/content/browser/power_save_blocker_impl.h +++ b/content/browser/power_save_blocker_impl.h
@@ -9,10 +9,11 @@ #include "base/memory/ref_counted.h" #include "content/public/browser/power_save_blocker.h" -#include "ui/gfx/native_widget_types.h" namespace content { +class WebContents; + class PowerSaveBlockerImpl : public PowerSaveBlocker { public: PowerSaveBlockerImpl(PowerSaveBlockerType type, @@ -22,9 +23,9 @@ #if defined(OS_ANDROID) // In Android platform, the kPowerSaveBlockPreventDisplaySleep type of - // PowerSaveBlocker should associated with the ViewAndroid, - // so the blocker could be removed by platform if the view isn't visble - void InitDisplaySleepBlocker(gfx::NativeView view_android); + // PowerSaveBlocker should associated with a WebContents, so the blocker + // could be removed by platform if the WebContents is hidden. + void InitDisplaySleepBlocker(WebContents* web_contents); #endif private:
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc index f583a94..a336a7e 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc +++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -4,18 +4,77 @@ #include "content/browser/renderer_host/media/video_capture_buffer_pool.h" -#include "base/bind.h" -#include "base/callback.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/stl_util.h" -#include "media/base/video_frame.h" -#include "media/base/video_util.h" + +using media::VideoFrame; namespace content { const int VideoCaptureBufferPool::kInvalidId = -1; +VideoFrame::Format VideoPixelFormatToVideoFrameFormat( + media::VideoPixelFormat pixel_format) { + static struct { + media::VideoPixelFormat pixel_format; + VideoFrame::Format frame_format; + } const kVideoPixelFormatToVideoFrameFormat[] = { + {media::PIXEL_FORMAT_I420, VideoFrame::I420}, + {media::PIXEL_FORMAT_ARGB, VideoFrame::ARGB}, + {media::PIXEL_FORMAT_TEXTURE, VideoFrame::NATIVE_TEXTURE}, + }; + + for (const auto& format_pair : kVideoPixelFormatToVideoFrameFormat) { + if (format_pair.pixel_format == pixel_format) + return format_pair.frame_format; + } + LOG(ERROR) << "Unsupported VideoPixelFormat " + << media::VideoCaptureFormat::PixelFormatToString(pixel_format); + return VideoFrame::UNKNOWN; +} + +// Tracker specifics for SharedMemory. +class VideoCaptureBufferPool::SharedMemTracker final : public Tracker { + public: + SharedMemTracker(); + + bool Init(VideoFrame::Format format, const gfx::Size& dimensions) override; + void* storage() override { return shared_memory_.memory(); } + size_t requested_size() override { return shared_memory_.requested_size(); } + size_t mapped_size() override { return shared_memory_.mapped_size(); } + + bool ShareToProcess(base::ProcessHandle process_handle, + base::SharedMemoryHandle* new_handle) override { + return shared_memory_.ShareToProcess(process_handle, new_handle); + } + + private: + // The memory created to be shared with renderer processes. + base::SharedMemory shared_memory_; +}; + +VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker() + : Tracker() {} + +bool VideoCaptureBufferPool::SharedMemTracker::Init( + VideoFrame::Format format, + const gfx::Size& dimensions) { + // Input |dimensions| can be 0x0 for trackers that do not require memory + // backing. The allocated size is calculated using VideoFrame methods since + // this will be the abstraction used to wrap the underlying data. + return shared_memory_.CreateAndMapAnonymous( + VideoFrame::AllocationSize(format, dimensions)); +} + +//static +scoped_ptr<VideoCaptureBufferPool::Tracker> +VideoCaptureBufferPool::Tracker::CreateTracker() { + return make_scoped_ptr(new SharedMemTracker()); +} + +VideoCaptureBufferPool::Tracker::~Tracker() {} + VideoCaptureBufferPool::VideoCaptureBufferPool(int count) : count_(count), next_buffer_id_(0) { @@ -23,7 +82,7 @@ } VideoCaptureBufferPool::~VideoCaptureBufferPool() { - STLDeleteValues(&buffers_); + STLDeleteValues(&trackers_); } base::SharedMemoryHandle VideoCaptureBufferPool::ShareToProcess( @@ -32,140 +91,148 @@ size_t* memory_size) { base::AutoLock lock(lock_); - Buffer* buffer = GetBuffer(buffer_id); - if (!buffer) { + Tracker* tracker = GetTracker(buffer_id); + if (!tracker) { NOTREACHED() << "Invalid buffer_id."; return base::SharedMemory::NULLHandle(); } base::SharedMemoryHandle remote_handle; - buffer->shared_memory.ShareToProcess(process_handle, &remote_handle); - *memory_size = buffer->shared_memory.requested_size(); - return remote_handle; + if (tracker->ShareToProcess(process_handle, &remote_handle)) { + *memory_size = tracker->mapped_size(); + return remote_handle; + } + DPLOG(ERROR) << "Error mapping Shared Memory."; + return base::SharedMemoryHandle(); } bool VideoCaptureBufferPool::GetBufferInfo(int buffer_id, - void** memory, + void** storage, size_t* size) { base::AutoLock lock(lock_); - Buffer* buffer = GetBuffer(buffer_id); - if (!buffer) { + Tracker* tracker = GetTracker(buffer_id); + if (!tracker) { NOTREACHED() << "Invalid buffer_id."; return false; } - DCHECK(buffer->held_by_producer); - *memory = buffer->shared_memory.memory(); - *size = buffer->shared_memory.mapped_size(); + DCHECK(tracker->held_by_producer()); + *storage = tracker->storage(); + *size = tracker->mapped_size(); return true; } -int VideoCaptureBufferPool::ReserveForProducer(size_t size, +int VideoCaptureBufferPool::ReserveForProducer(media::VideoPixelFormat format, + const gfx::Size& dimensions, int* buffer_id_to_drop) { base::AutoLock lock(lock_); - return ReserveForProducerInternal(size, buffer_id_to_drop); + return ReserveForProducerInternal(format, dimensions, buffer_id_to_drop); } void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) { base::AutoLock lock(lock_); - Buffer* buffer = GetBuffer(buffer_id); - if (!buffer) { + Tracker* tracker = GetTracker(buffer_id); + if (!tracker) { NOTREACHED() << "Invalid buffer_id."; return; } - DCHECK(buffer->held_by_producer); - buffer->held_by_producer = false; + DCHECK(tracker->held_by_producer()); + tracker->set_held_by_producer(false); } void VideoCaptureBufferPool::HoldForConsumers( int buffer_id, int num_clients) { base::AutoLock lock(lock_); - Buffer* buffer = GetBuffer(buffer_id); - if (!buffer) { + Tracker* tracker = GetTracker(buffer_id); + if (!tracker) { NOTREACHED() << "Invalid buffer_id."; return; } - DCHECK(buffer->held_by_producer); - DCHECK(!buffer->consumer_hold_count); + DCHECK(tracker->held_by_producer()); + DCHECK(!tracker->consumer_hold_count()); - buffer->consumer_hold_count = num_clients; - // Note: |held_by_producer| will stay true until + tracker->set_consumer_hold_count(num_clients); + // Note: |held_by_producer()| will stay true until // RelinquishProducerReservation() (usually called by destructor of the object - // wrapping this buffer, e.g. a media::VideoFrame). + // wrapping this tracker, e.g. a media::VideoFrame). } void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id, int num_clients) { base::AutoLock lock(lock_); - Buffer* buffer = GetBuffer(buffer_id); - if (!buffer) { + Tracker* tracker = GetTracker(buffer_id); + if (!tracker) { NOTREACHED() << "Invalid buffer_id."; return; } - DCHECK_GE(buffer->consumer_hold_count, num_clients); + DCHECK_GE(tracker->consumer_hold_count(), num_clients); - buffer->consumer_hold_count -= num_clients; + tracker->set_consumer_hold_count(tracker->consumer_hold_count() - + num_clients); } -VideoCaptureBufferPool::Buffer::Buffer() - : held_by_producer(false), consumer_hold_count(0) {} - -int VideoCaptureBufferPool::ReserveForProducerInternal(size_t size, - int* buffer_id_to_drop) { +int VideoCaptureBufferPool::ReserveForProducerInternal( + media::VideoPixelFormat format, + const gfx::Size& dimensions, + int* buffer_id_to_drop) { + DCHECK(format == media::PIXEL_FORMAT_I420 || + format == media::PIXEL_FORMAT_ARGB || + format == media::PIXEL_FORMAT_TEXTURE); lock_.AssertAcquired(); + const media::VideoFrame::Format frame_format = + VideoPixelFormatToVideoFrameFormat(format); + const size_t size_in_bytes = + VideoFrame::AllocationSize(frame_format, dimensions); - // Look for a buffer that's allocated, big enough, and not in use. Track the - // largest one that's not big enough, in case we have to reallocate a buffer. + // Look for a tracker that's allocated, big enough, and not in use. Track the + // largest one that's not big enough, in case we have to reallocate a tracker. *buffer_id_to_drop = kInvalidId; size_t realloc_size = 0; - BufferMap::iterator realloc = buffers_.end(); - for (BufferMap::iterator it = buffers_.begin(); it != buffers_.end(); ++it) { - Buffer* buffer = it->second; - if (!buffer->consumer_hold_count && !buffer->held_by_producer) { - if (buffer->shared_memory.requested_size() >= size) { - // Existing buffer is big enough. Reuse it. - buffer->held_by_producer = true; + TrackerMap::iterator tracker_to_drop = trackers_.end(); + for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end(); + ++it) { + Tracker* const tracker = it->second; + if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) { + if (tracker->requested_size() >= size_in_bytes) { + // Existing tracker is big enough. Reuse it. + tracker->set_held_by_producer(true); return it->first; } - if (buffer->shared_memory.requested_size() > realloc_size) { - realloc_size = buffer->shared_memory.requested_size(); - realloc = it; + if (tracker->requested_size() > realloc_size) { + realloc_size = tracker->requested_size(); + tracker_to_drop = it; } } } - // Preferentially grow the pool by creating a new buffer. If we're at maximum + // Preferably grow the pool by creating a new tracker. If we're at maximum // size, then reallocate by deleting an existing one instead. - if (buffers_.size() == static_cast<size_t>(count_)) { - if (realloc == buffers_.end()) { - // We're out of space, and can't find an unused buffer to reallocate. + if (trackers_.size() == static_cast<size_t>(count_)) { + if (tracker_to_drop == trackers_.end()) { + // We're out of space, and can't find an unused tracker to reallocate. return kInvalidId; } - *buffer_id_to_drop = realloc->first; - delete realloc->second; - buffers_.erase(realloc); + *buffer_id_to_drop = tracker_to_drop->first; + delete tracker_to_drop->second; + trackers_.erase(tracker_to_drop); } - // Create the new buffer. - int buffer_id = next_buffer_id_++; - scoped_ptr<Buffer> buffer(new Buffer()); - if (size) { - // |size| can be 0 for buffers that do not require memory backing. - if (!buffer->shared_memory.CreateAndMapAnonymous(size)) - return kInvalidId; - } - buffer->held_by_producer = true; - buffers_[buffer_id] = buffer.release(); + // Create the new tracker. + const int buffer_id = next_buffer_id_++; + scoped_ptr<Tracker> tracker = Tracker::CreateTracker(); + if (!tracker->Init(frame_format, dimensions)) + return kInvalidId; + tracker->set_held_by_producer(true); + trackers_[buffer_id] = tracker.release(); + return buffer_id; } -VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer( +VideoCaptureBufferPool::Tracker* VideoCaptureBufferPool::GetTracker( int buffer_id) { - BufferMap::iterator it = buffers_.find(buffer_id); - if (it == buffers_.end()) - return NULL; - return it->second; + TrackerMap::const_iterator it = trackers_.find(buffer_id); + return (it == trackers_.end()) ? NULL : it->second; } } // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.h b/content/browser/renderer_host/media/video_capture_buffer_pool.h index 54cb0c34..2546499 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool.h +++ b/content/browser/renderer_host/media/video_capture_buffer_pool.h
@@ -14,21 +14,18 @@ #include "base/process/process.h" #include "base/synchronization/lock.h" #include "content/common/content_export.h" +#include "media/base/video_capture_types.h" +#include "media/base/video_frame.h" #include "ui/gfx/geometry/size.h" -namespace media { - -class VideoFrame; - -} // namespace media - namespace content { // A thread-safe class that does the bookkeeping and lifetime management for a -// pool of shared-memory pixel buffers cycled between an in-process producer -// (e.g. a VideoCaptureDevice) and a set of out-of-process consumers. The pool -// is intended to be orchestrated by a VideoCaptureController, but is designed -// to outlive the controller if necessary. +// pool of pixel buffers cycled between an in-process producer (e.g. a +// VideoCaptureDevice) and a set of out-of-process consumers. The pool is +// intended to be orchestrated by a VideoCaptureController, but is designed +// to outlive the controller if necessary. The pixel buffers may be backed by a +// SharedMemory, but this is not compulsory. // // Producers get a buffer by calling ReserveForProducer(), and may pass on their // ownership to the consumer by calling HoldForConsumers(), or drop the buffer @@ -58,12 +55,12 @@ // Query the memory parameters of |buffer_id|. Fills in parameters in the // pointer arguments, and returns true iff the buffer exists. - bool GetBufferInfo(int buffer_id, void** memory, size_t* size); + bool GetBufferInfo(int buffer_id, void** storage, size_t* size); - // Reserve or allocate a buffer of at least |size| bytes and return its id. - // This will fail (returning kInvalidId) if the pool already is at its |count| - // limit of the number of allocations, and all allocated buffers are in use by - // the producer and/or consumers. + // Reserve or allocate a buffer to support a packed frame of |dimensions| of + // pixel |format| and return its id. This will fail (returning kInvalidId) if + // the pool already is at its |count| limit of the number of allocations, and + // all allocated buffers are in use by the producer and/or consumers. // // If successful, the reserved buffer remains reserved (and writable by the // producer) until ownership is transferred either to the consumer via @@ -73,7 +70,9 @@ // On occasion, this call will decide to free an old buffer to make room for a // new allocation at a larger size. If so, the ID of the destroyed buffer is // returned via |buffer_id_to_drop|. - int ReserveForProducer(size_t size, int* buffer_id_to_drop); + int ReserveForProducer(media::VideoPixelFormat format, + const gfx::Size& dimensions, + int* buffer_id_to_drop); // Indicate that a buffer held for the producer should be returned back to the // pool without passing on to the consumer. This effectively is the opposite @@ -90,32 +89,50 @@ // done, a buffer is returned to the pool for reuse. void RelinquishConsumerHold(int buffer_id, int num_clients); - int count() const { return count_; } - private: - friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>; + class SharedMemTracker; + // Generic class to keep track of the state of a given mappable resource. + class Tracker { + public: + static scoped_ptr<Tracker> CreateTracker(); - // Per-buffer state. - struct Buffer { - Buffer(); + Tracker() : held_by_producer_(false), consumer_hold_count_(0) {} + virtual bool Init(media::VideoFrame::Format format, + const gfx::Size& dimensions) = 0; + virtual ~Tracker(); - // The memory created to be shared with renderer processes. - base::SharedMemory shared_memory; + bool held_by_producer() const { return held_by_producer_; } + void set_held_by_producer(bool value) { held_by_producer_ = value; } + int consumer_hold_count() const { return consumer_hold_count_; } + void set_consumer_hold_count(int value) { consumer_hold_count_ = value; } - // Tracks whether this buffer is currently referenced by the producer. - bool held_by_producer; + // Returns a void* to the underlying storage, be that a memory block for + // Shared Memory, or a GpuMemoryBuffer. + virtual void* storage() = 0; + // Amount of bytes requested when first created. Can be zero if it does not + // need RAM, e.g. is allocated in GPU memory. + virtual size_t requested_size() = 0; + // The actual size of the underlying backing resource. + virtual size_t mapped_size() = 0; - // Number of consumer processes which hold this shared memory. - int consumer_hold_count; + virtual bool ShareToProcess(base::ProcessHandle process_handle, + base::SharedMemoryHandle* new_handle) = 0; + + private: + // Indicates whether this Tracker is currently referenced by the producer. + bool held_by_producer_; + // Number of consumer processes which hold this Tracker. + int consumer_hold_count_; }; - typedef std::map<int, Buffer*> BufferMap; - + friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>; virtual ~VideoCaptureBufferPool(); - int ReserveForProducerInternal(size_t size, int* buffer_id_to_drop); + int ReserveForProducerInternal(media::VideoPixelFormat format, + const gfx::Size& dimensions, + int* tracker_id_to_drop); - Buffer* GetBuffer(int buffer_id); + Tracker* GetTracker(int buffer_id); // The max number of buffers that the pool is allowed to have at any moment. const int count_; @@ -126,8 +143,9 @@ // The ID of the next buffer. int next_buffer_id_; - // The buffers, indexed by |buffer_id|. - BufferMap buffers_; + // The buffers, indexed by the first parameter, a buffer id. + using TrackerMap = std::map<int, Tracker*>; + TrackerMap trackers_; DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureBufferPool); };
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc index 39fd985..e8f446f 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -45,12 +45,11 @@ } scoped_ptr<Buffer> ReserveI420Buffer(const gfx::Size& dimensions) { - const size_t frame_bytes = - media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions); // To verify that ReserveI420Buffer always sets |buffer_id_to_drop|, // initialize it to something different than the expected value. int buffer_id_to_drop = ~expected_dropped_id_; - int buffer_id = pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); + int buffer_id = pool_->ReserveForProducer(media::PIXEL_FORMAT_I420, + dimensions, &buffer_id_to_drop); if (buffer_id == VideoCaptureBufferPool::kInvalidId) return scoped_ptr<Buffer>();
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index 7e8f055..1cbd287 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -326,8 +326,8 @@ // side effect this will cause the first buffer to be shared with clients. uint8 buffer_no = 1; scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer; - buffer = - device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, + capture_resolution); ASSERT_TRUE(buffer.get()); memset(buffer->data(), buffer_no++, buffer->size()); { @@ -358,8 +358,8 @@ // Second buffer which ought to use the same shared memory buffer. In this // case pretend that the Buffer pointer is held by the device for a long // delay. This shouldn't affect anything. - buffer = - device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, + capture_resolution); ASSERT_TRUE(buffer.get()); memset(buffer->data(), buffer_no++, buffer->size()); device_->OnIncomingCapturedVideoFrame( @@ -386,7 +386,7 @@ // Third, fourth, and fifth buffers. Pretend they all arrive at the same time. for (int i = 0; i < kPoolSize; i++) { - buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420, + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, capture_resolution); ASSERT_TRUE(buffer.get()); memset(buffer->data(), buffer_no++, buffer->size()); @@ -397,7 +397,7 @@ buffer = NULL; } // ReserveOutputBuffer ought to fail now, because the pool is depleted. - ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420, + ASSERT_FALSE(device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, capture_resolution).get()); // The new client needs to be told of 3 buffers; the old clients only 2. @@ -423,8 +423,8 @@ EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1); controller_->StopSession(300); // Queue up another buffer. - buffer = - device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, + capture_resolution); ASSERT_TRUE(buffer.get()); memset(buffer->data(), buffer_no++, buffer->size()); device_->OnIncomingCapturedVideoFrame( @@ -432,8 +432,8 @@ WrapI420Buffer(buffer, capture_resolution), base::TimeTicks()); buffer = NULL; - buffer = - device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, + capture_resolution); { // Kill A2 via session close (posts a task to disconnect, but A2 must not // be sent either of these two buffers). @@ -469,7 +469,7 @@ } for (int i = 0; i < shm_buffers; ++i) { - buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420, + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, capture_resolution); ASSERT_TRUE(buffer.get()); device_->OnIncomingCapturedVideoFrame( @@ -481,8 +481,8 @@ std::vector<uint32> mailbox_syncpoints(mailbox_buffers); std::vector<uint32> release_syncpoints(mailbox_buffers); for (int i = 0; i < mailbox_buffers; ++i) { - buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE, - gfx::Size(0, 0)); + buffer = device_->ReserveOutputBuffer(media::PIXEL_FORMAT_TEXTURE, + capture_resolution); ASSERT_TRUE(buffer.get()); #if !defined(OS_ANDROID) mailbox_syncpoints[i] = gl_helper->InsertSyncPoint(); @@ -498,10 +498,10 @@ } // ReserveOutputBuffers ought to fail now regardless of buffer format, because // the pool is depleted. - ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420, + ASSERT_FALSE(device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, capture_resolution).get()); - ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE, - gfx::Size(0, 0)).get()); + ASSERT_FALSE(device_->ReserveOutputBuffer(media::PIXEL_FORMAT_TEXTURE, + capture_resolution).get()); EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2,_)).Times(shm_buffers); EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2)) .Times(mailbox_buffers); @@ -550,7 +550,8 @@ Mock::VerifyAndClearExpectations(client_b_.get()); scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer = - device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution); + device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, + capture_resolution); ASSERT_TRUE(buffer.get()); device_->OnIncomingCapturedVideoFrame( @@ -587,7 +588,7 @@ const gfx::Size dims(320, 240); scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer = - device_->ReserveOutputBuffer(media::VideoFrame::I420, dims); + device_->ReserveOutputBuffer(media::PIXEL_FORMAT_I420, dims); ASSERT_TRUE(buffer.get()); device_->OnError("Test error");
diff --git a/content/browser/renderer_host/media/video_capture_device_client.cc b/content/browser/renderer_host/media/video_capture_device_client.cc index 001e111..66b7fdb 100644 --- a/content/browser/renderer_host/media/video_capture_device_client.cc +++ b/content/browser/renderer_host/media/video_capture_device_client.cc
@@ -105,8 +105,8 @@ return; } - scoped_refptr<Buffer> buffer = ReserveOutputBuffer(VideoFrame::I420, - dimensions); + scoped_refptr<Buffer> buffer = + ReserveOutputBuffer(media::PIXEL_FORMAT_I420, dimensions); if (!buffer.get()) return; @@ -243,8 +243,8 @@ DCHECK_EQ(frame_format.pixel_format, media::PIXEL_FORMAT_I420); DCHECK_EQ(clockwise_rotation, 0) << "Rotation not supported"; - scoped_refptr<Buffer> buffer = ReserveOutputBuffer(VideoFrame::I420, - frame_format.frame_size); + scoped_refptr<Buffer> buffer = + ReserveOutputBuffer(frame_format.pixel_format, frame_format.frame_size); if (!buffer.get()) return; @@ -301,19 +301,17 @@ }; scoped_refptr<media::VideoCaptureDevice::Client::Buffer> -VideoCaptureDeviceClient::ReserveOutputBuffer(VideoFrame::Format format, +VideoCaptureDeviceClient::ReserveOutputBuffer(media::VideoPixelFormat format, const gfx::Size& dimensions) { - const size_t frame_bytes = VideoFrame::AllocationSize(format, dimensions); - if (format == VideoFrame::NATIVE_TEXTURE) { - DCHECK_EQ(dimensions.width(), 0); - DCHECK_EQ(dimensions.height(), 0); - } else { - DLOG_IF(ERROR, frame_bytes == 0) << "Error calculating allocation size"; - } + DCHECK(format == media::PIXEL_FORMAT_TEXTURE || + format == media::PIXEL_FORMAT_I420 || + format == media::PIXEL_FORMAT_ARGB); + DCHECK_GT(dimensions.width(), 0); + DCHECK_GT(dimensions.height(), 0); int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; const int buffer_id = - buffer_pool_->ReserveForProducer(frame_bytes, &buffer_id_to_drop); + buffer_pool_->ReserveForProducer(format, dimensions, &buffer_id_to_drop); if (buffer_id == VideoCaptureBufferPool::kInvalidId) return NULL; void* data;
diff --git a/content/browser/renderer_host/media/video_capture_device_client.h b/content/browser/renderer_host/media/video_capture_device_client.h index 3abfb95..7da95da 100644 --- a/content/browser/renderer_host/media/video_capture_device_client.h +++ b/content/browser/renderer_host/media/video_capture_device_client.h
@@ -47,8 +47,9 @@ const media::VideoCaptureFormat& frame_format, int clockwise_rotation, const base::TimeTicks& timestamp) override; - scoped_refptr<Buffer> ReserveOutputBuffer(media::VideoFrame::Format format, - const gfx::Size& size) override; + scoped_refptr<Buffer> ReserveOutputBuffer( + media::VideoPixelFormat format, + const gfx::Size& dimensions) override; void OnIncomingCapturedVideoFrame( const scoped_refptr<Buffer>& buffer, const scoped_refptr<media::VideoFrame>& frame,
diff --git a/content/browser/renderer_host/media/video_capture_texture_wrapper.cc b/content/browser/renderer_host/media/video_capture_texture_wrapper.cc index ed4adcaa..7c14a15 100644 --- a/content/browser/renderer_host/media/video_capture_texture_wrapper.cc +++ b/content/browser/renderer_host/media/video_capture_texture_wrapper.cc
@@ -210,7 +210,7 @@ // Reserve a temporary Buffer for conversion to ARGB. scoped_refptr<media::VideoCaptureDevice::Client::Buffer> argb_buffer = - ReserveOutputBuffer(media::VideoFrame::ARGB, frame_format.frame_size); + ReserveOutputBuffer(media::PIXEL_FORMAT_ARGB, frame_format.frame_size); DVLOG_IF(1, !argb_buffer) << "Couldn't allocate ARGB Buffer"; if (!argb_buffer) return; @@ -236,7 +236,7 @@ // Reserve output buffer for the texture on the IPC borderlands. scoped_refptr<media::VideoCaptureDevice::Client::Buffer> texture_buffer = - ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE, gfx::Size()); + ReserveOutputBuffer(media::PIXEL_FORMAT_TEXTURE, frame_format.frame_size); DVLOG_IF(1, !texture_buffer) << "Couldn't allocate Texture Buffer"; if (!texture_buffer) return;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 91dd8b3..4ea27a1 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -335,6 +335,20 @@ bool* success) { AddBaseHandleClosePolicy(policy); + if (base::win::GetVersion() == base::win::VERSION_WIN8 || + base::win::GetVersion() == base::win::VERSION_WIN8_1) { + // TODO(shrikant): Check if these constants should be different across + // various versions of Chromium code base or could be same. + // If there should be different SID per channel then move this code + // in chrome rather than content and assign SID based on + // VersionInfo::GetChannel(). + const wchar_t kAppContainerSid[] = + L"S-1-15-2-3251537155-1984446955-2931258699-841473695-1938553385-" + L"924012148-129201922"; + + policy->SetLowBox(kAppContainerSid); + } + GetContentClient()->browser()->PreSpawnRenderer(policy, success); } @@ -689,11 +703,10 @@ channel_mojo_host_.reset(new IPC::ChannelMojoHost(mojo_task_runner)); } - return IPC::ChannelProxy::Create( - IPC::ChannelMojo::CreateServerFactory( - channel_mojo_host_->channel_delegate(), channel_id), - this, - runner.get()); + return IPC::ChannelProxy::Create(IPC::ChannelMojo::CreateServerFactory( + channel_mojo_host_->channel_delegate(), + mojo_task_runner, channel_id), + this, runner.get()); } return IPC::ChannelProxy::Create(
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index cee439c..2697e5e7 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -21,7 +21,6 @@ class SkBitmap; struct ViewHostMsg_CreateWindow_Params; struct FrameHostMsg_DidCommitProvisionalLoad_Params; -struct ViewMsg_PostMessage_Params; namespace base { class ListValue; @@ -129,11 +128,6 @@ // The page wants to close the active view in this tab. virtual void RouteCloseEvent(RenderViewHost* rvh) {} - // The page wants to post a message to the active view in this tab. - virtual void RouteMessageEvent( - RenderViewHost* rvh, - const ViewMsg_PostMessage_Params& params) {} - // Return a dummy RendererPreferences object that will be used by the renderer // associated with the owning RenderViewHost. virtual RendererPreferences GetRendererPrefs(
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 730860e8..3a7af0c 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -357,9 +357,12 @@ } void RenderViewHostImpl::SyncRendererPrefs() { - Send(new ViewMsg_SetRendererPrefs(GetRoutingID(), - delegate_->GetRendererPrefs( - GetProcess()->GetBrowserContext()))); + RendererPreferences renderer_preferences = + delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext()); +#if defined(OS_WIN) + GetWindowsSpecificPrefs(&renderer_preferences); +#endif + Send(new ViewMsg_SetRendererPrefs(GetRoutingID(), renderer_preferences)); } WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() { @@ -897,7 +900,6 @@ OnDidContentsPreferredSizeChange) IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent, OnRouteCloseEvent) - IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent, OnRouteMessageEvent) IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging) IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor) IPC_MESSAGE_HANDLER(DragHostMsg_TargetDrop_ACK, OnTargetDropACK) @@ -1091,12 +1093,6 @@ delegate_->RouteCloseEvent(this); } -void RenderViewHostImpl::OnRouteMessageEvent( - const ViewMsg_PostMessage_Params& params) { - // Give to the delegate to route to the active RenderViewHost. - delegate_->RouteMessageEvent(this, params); -} - void RenderViewHostImpl::OnStartDragging( const DropData& drop_data, WebDragOperationsMask drag_operations_mask,
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index 15883b6..3e6b0154 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -348,7 +348,6 @@ void OnDidContentsPreferredSizeChange(const gfx::Size& new_size); void OnPasteFromSelectionClipboard(); void OnRouteCloseEvent(); - void OnRouteMessageEvent(const ViewMsg_PostMessage_Params& params); void OnStartDragging(const DropData& drop_data, blink::WebDragOperationsMask operations_allowed, const SkBitmap& bitmap,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 318584e..337c9bc 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1686,9 +1686,12 @@ return INPUT_EVENT_ACK_STATE_CONSUMED; } - if (content_view_core_ && - content_view_core_->FilterInputEvent(input_event)) - return INPUT_EVENT_ACK_STATE_CONSUMED; + if (content_view_core_) { + InputEventAckState ack_result = + content_view_core_->FilterInputEvent(input_event); + if (ack_result != INPUT_EVENT_ACK_STATE_NOT_CONSUMED) + return ack_result; + } if (!host_) return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index ea54c6d..95687bf 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -1821,4 +1821,89 @@ } } +// Check that postMessage can be routed between cross-site iframes. +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SubframePostMessage) { + GURL main_url(embedded_test_server()->GetURL( + "/frame_tree/page_with_post_message_frames.html")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + // It is safe to obtain the root frame tree node here, as it doesn't change. + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + + TestNavigationObserver observer(shell()->web_contents()); + ASSERT_EQ(2U, root->child_count()); + + // Verify the frames start at correct URLs. First frame should be + // same-site; second frame should be cross-site. + GURL same_site_url(embedded_test_server()->GetURL("/post_message.html")); + EXPECT_EQ(same_site_url, root->child_at(0)->current_url()); + GURL foo_url(embedded_test_server()->GetURL("foo.com", + "/post_message.html")); + EXPECT_EQ(foo_url, root->child_at(1)->current_url()); + EXPECT_NE(root->child_at(0)->current_frame_host()->GetSiteInstance(), + root->child_at(1)->current_frame_host()->GetSiteInstance()); + + // Send a message from first, same-site frame to second, cross-site frame. + // Expect the second frame to reply back to the first frame. + // + // TODO(alexmos): Also try sending from second to first frame. Currently, + // this fails due to https://crbug.com/473518, which prevents + // parent.frames[x] from working when "parent" is a remote frame. + bool success = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool( + root->child_at(0)->current_frame_host(), + "window.domAutomationController.send(" + " postToSibling('subframe-msg','subframe2'));", + &success)); + EXPECT_TRUE(success); + + // Wait for first frame to receive a reply from the second frame. It will + // send "done-subframe1" from the DOMAutomationController when the reply + // arrives. + content::DOMMessageQueue msg_queue; + std::string status; + while (msg_queue.WaitForMessage(&status)) { + if (status == "\"done-subframe1\"") + break; + } + + // Send a postMessage from second, cross-site frame to its parent. Expect + // parent to send a reply to the frame. + base::string16 expected_title(base::ASCIIToUTF16("subframe-msg")); + TitleWatcher title_watcher(shell()->web_contents(), expected_title); + success = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool( + root->child_at(1)->current_frame_host(), + "window.domAutomationController.send(postToParent('subframe-msg'));", + &success)); + EXPECT_TRUE(success); + EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); + + // Wait for second frame to receive a reply from the parent. The frame will + // return "done-subframe2" from the DOMAutomationController when the reply + // arrives. + while (msg_queue.WaitForMessage(&status)) { + if (status == "\"done-subframe2\"") + break; + } + + // Verify the total number of received messages for each subframe. First + // frame should have one message (reply from second frame), and second frame + // should have two messages (message from first frame and reply from parent). + int subframe1_received_messages = 0; + int subframe2_received_messages = 0; + EXPECT_TRUE(ExecuteScriptAndExtractInt( + root->child_at(0)->current_frame_host(), + "window.domAutomationController.send(window.receivedMessages);", + &subframe1_received_messages)); + EXPECT_EQ(1, subframe1_received_messages); + EXPECT_TRUE(ExecuteScriptAndExtractInt( + root->child_at(1)->current_frame_host(), + "window.domAutomationController.send(window.receivedMessages);", + &subframe2_received_messages)); + EXPECT_EQ(2, subframe2_received_messages); +} + } // namespace content
diff --git a/content/browser/web_contents/aura/shadow_layer_delegate.cc b/content/browser/web_contents/aura/shadow_layer_delegate.cc index 5454307..a38d5ca 100644 --- a/content/browser/web_contents/aura/shadow_layer_delegate.cc +++ b/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -50,8 +50,7 @@ SkPaint paint; paint.setShader(shader.get()); ui::PaintRecorder recorder(context); - recorder.canvas()->sk_canvas()->drawRect(gfx::RectToSkRect(paint_rect), - paint); + recorder.canvas()->DrawRect(paint_rect, paint); } void ShadowLayerDelegate::OnDelegatedFrameDamage(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index a37400ce0..55a291d 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3220,7 +3220,7 @@ PowerSaveBlocker::kReasonVideoPlayback, "Playing video"); #if defined(OS_ANDROID) static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get()) - ->InitDisplaySleepBlocker(GetView()->GetNativeView()); + ->InitDisplaySleepBlocker(this); #endif } @@ -3997,74 +3997,36 @@ GetRenderViewHost()->ClosePage(); } -void WebContentsImpl::RouteMessageEvent( - RenderViewHost* rvh, - const ViewMsg_PostMessage_Params& params) { - // Only deliver the message to the active RenderViewHost if the request - // came from a RenderViewHost in the same BrowsingInstance or if this - // WebContents is dedicated to a browser plugin guest. +bool WebContentsImpl::ShouldRouteMessageEvent( + RenderFrameHost* target_rfh, + SiteInstance* source_site_instance) const { + // Allow the message if this WebContents is dedicated to a browser plugin + // guest. // Note: This check means that an embedder could theoretically receive a // postMessage from anyone (not just its own guests). However, this is // probably not a risk for apps since other pages won't have references // to App windows. - if (!rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance()) && - !GetBrowserPluginGuest() && !GetBrowserPluginEmbedder()) - return; + return GetBrowserPluginGuest() || GetBrowserPluginEmbedder(); +} - ViewMsg_PostMessage_Params new_params(params); +int WebContentsImpl::EnsureOpenerRenderViewsExist( + RenderFrameHost* source_rfh) { + WebContentsImpl* source_web_contents = static_cast<WebContentsImpl*>( + WebContents::FromRenderFrameHost(source_rfh)); - // If there is a source_routing_id, translate it to the routing ID for - // the equivalent swapped out RVH in the target process. If we need - // to create a swapped out RVH for the source tab, we create its opener - // chain as well, since those will also be accessible to the target page. - if (new_params.source_routing_id != MSG_ROUTING_NONE) { - // Try to look up the WebContents for the source page. - WebContentsImpl* source_contents = NULL; - RenderViewHostImpl* source_rvh = RenderViewHostImpl::FromID( - rvh->GetProcess()->GetID(), params.source_routing_id); - if (source_rvh) { - source_contents = static_cast<WebContentsImpl*>( - source_rvh->GetDelegate()->GetAsWebContents()); - } - - if (source_contents) { - if (GetBrowserPluginGuest()) { - // We create a swapped out RenderView for the embedder in the guest's - // render process but we intentionally do not expose the embedder's - // opener chain to it. - new_params.source_routing_id = - source_contents->CreateSwappedOutRenderView(GetSiteInstance()); - } else { - new_params.source_routing_id = - source_contents->CreateOpenerRenderViews(GetSiteInstance()); - } + if (source_web_contents) { + if (GetBrowserPluginGuest()) { + // We create a swapped out RenderView for the embedder in the guest's + // render process but we intentionally do not expose the embedder's + // opener chain to it. + return + source_web_contents->CreateSwappedOutRenderView(GetSiteInstance()); } else { - // We couldn't find it, so don't pass a source frame. - new_params.source_routing_id = MSG_ROUTING_NONE; + return source_web_contents->CreateOpenerRenderViews(GetSiteInstance()); } } - // In most cases, we receive this from a swapped out RenderViewHost. - // It is possible to receive it from one that has just been swapped in, - // in which case we might as well deliver the message anyway. - if (!params.message_ports.empty()) { - // Updating the message port information has to be done in the IO thread; - // MessagePortMessageFilter::RouteMessageEventWithMessagePorts will send - // ViewMsg_PostMessageEvent after it's done. Note that a trivial solution - // would've been to post a task on the IO thread to do the IO-thread-bound - // work, and make that post a task back to WebContentsImpl in the UI - // thread. But we cannot do that, since there's nothing to guarantee that - // WebContentsImpl stays alive during the round trip. - scoped_refptr<MessagePortMessageFilter> message_port_message_filter( - static_cast<RenderProcessHostImpl*>(GetRenderProcessHost()) - ->message_port_message_filter()); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&MessagePortMessageFilter::RouteMessageEventWithMessagePorts, - message_port_message_filter, GetRoutingID(), new_params)); - } else { - Send(new ViewMsg_PostMessageEvent(GetRoutingID(), new_params)); - } + return MSG_ROUTING_NONE; } bool WebContentsImpl::AddMessageToConsole(int32 level,
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 6753535..3c45bd5 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -43,7 +43,6 @@ struct BrowserPluginHostMsg_ResizeGuest_Params; struct ViewHostMsg_DateTimeDialogValue_Params; -struct ViewMsg_PostMessage_Params; namespace content { class BrowserPluginEmbedder; @@ -412,6 +411,10 @@ GeolocationServiceContext* GetGeolocationServiceContext() override; void EnterFullscreenMode(const GURL& origin) override; void ExitFullscreenMode() override; + bool ShouldRouteMessageEvent( + RenderFrameHost* target_rfh, + SiteInstance* source_site_instance) const override; + int EnsureOpenerRenderViewsExist(RenderFrameHost* source_rfh) override; #if defined(OS_WIN) gfx::NativeViewAccessible GetParentNativeViewAccessible() override; #endif @@ -440,8 +443,6 @@ void DidCancelLoading() override; void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) override; void RouteCloseEvent(RenderViewHost* rvh) override; - void RouteMessageEvent(RenderViewHost* rvh, - const ViewMsg_PostMessage_Params& params) override; bool AddMessageToConsole(int32 level, const base::string16& message, int32 line_no,
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 454a2b3..2c71a25 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -739,133 +739,133 @@ }; const DataResource kDataResources[] = { - {"missingImage", IDR2_BROKENIMAGE, ui::SCALE_FACTOR_100P}, - {"missingImage@2x", IDR2_BROKENIMAGE, ui::SCALE_FACTOR_200P}, - {"mediaplayerPause", IDR2_MEDIAPLAYER_PAUSE_BUTTON, ui::SCALE_FACTOR_100P}, + {"missingImage", IDR_BROKENIMAGE, ui::SCALE_FACTOR_100P}, + {"missingImage@2x", IDR_BROKENIMAGE, ui::SCALE_FACTOR_200P}, + {"mediaplayerPause", IDR_MEDIAPLAYER_PAUSE_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerPauseHover", - IDR2_MEDIAPLAYER_PAUSE_BUTTON_HOVER, + IDR_MEDIAPLAYER_PAUSE_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerPauseDown", - IDR2_MEDIAPLAYER_PAUSE_BUTTON_DOWN, + IDR_MEDIAPLAYER_PAUSE_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, - {"mediaplayerPlay", IDR2_MEDIAPLAYER_PLAY_BUTTON, ui::SCALE_FACTOR_100P}, + {"mediaplayerPlay", IDR_MEDIAPLAYER_PLAY_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerPlayHover", - IDR2_MEDIAPLAYER_PLAY_BUTTON_HOVER, + IDR_MEDIAPLAYER_PLAY_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerPlayDown", - IDR2_MEDIAPLAYER_PLAY_BUTTON_DOWN, + IDR_MEDIAPLAYER_PLAY_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerPlayDisabled", - IDR2_MEDIAPLAYER_PLAY_BUTTON_DISABLED, + IDR_MEDIAPLAYER_PLAY_BUTTON_DISABLED, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel3", - IDR2_MEDIAPLAYER_SOUND_LEVEL3_BUTTON, + IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel3Hover", - IDR2_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER, + IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel3Down", - IDR2_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN, + IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel2", - IDR2_MEDIAPLAYER_SOUND_LEVEL2_BUTTON, + IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel2Hover", - IDR2_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER, + IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel2Down", - IDR2_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN, + IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel1", - IDR2_MEDIAPLAYER_SOUND_LEVEL1_BUTTON, + IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel1Hover", - IDR2_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER, + IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel1Down", - IDR2_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN, + IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel0", - IDR2_MEDIAPLAYER_SOUND_LEVEL0_BUTTON, + IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel0Hover", - IDR2_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER, + IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundLevel0Down", - IDR2_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN, + IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerSoundDisabled", - IDR2_MEDIAPLAYER_SOUND_DISABLED, + IDR_MEDIAPLAYER_SOUND_DISABLED, ui::SCALE_FACTOR_100P}, {"mediaplayerSliderThumb", - IDR2_MEDIAPLAYER_SLIDER_THUMB, + IDR_MEDIAPLAYER_SLIDER_THUMB, ui::SCALE_FACTOR_100P}, {"mediaplayerSliderThumbHover", - IDR2_MEDIAPLAYER_SLIDER_THUMB_HOVER, + IDR_MEDIAPLAYER_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerSliderThumbDown", - IDR2_MEDIAPLAYER_SLIDER_THUMB_DOWN, + IDR_MEDIAPLAYER_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerVolumeSliderThumb", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB, ui::SCALE_FACTOR_100P}, {"mediaplayerVolumeSliderThumbHover", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerVolumeSliderThumbDown", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerVolumeSliderThumbDisabled", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED, ui::SCALE_FACTOR_100P}, {"mediaplayerClosedCaption", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerClosedCaptionHover", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerClosedCaptionDown", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerClosedCaptionDisabled", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED, ui::SCALE_FACTOR_100P}, {"mediaplayerFullscreen", - IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON, + IDR_MEDIAPLAYER_FULLSCREEN_BUTTON, ui::SCALE_FACTOR_100P}, {"mediaplayerFullscreenHover", - IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER, + IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER, ui::SCALE_FACTOR_100P}, {"mediaplayerFullscreenDown", - IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN, + IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN, ui::SCALE_FACTOR_100P}, {"mediaplayerCastOff", - IDR2_MEDIAPLAYER_CAST_BUTTON_OFF, + IDR_MEDIAPLAYER_CAST_BUTTON_OFF, ui::SCALE_FACTOR_100P}, {"mediaplayerCastOn", - IDR2_MEDIAPLAYER_CAST_BUTTON_ON, + IDR_MEDIAPLAYER_CAST_BUTTON_ON, ui::SCALE_FACTOR_100P}, {"mediaplayerFullscreenDisabled", - IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED, + IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED, ui::SCALE_FACTOR_100P}, {"mediaplayerOverlayCastOff", - IDR2_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF, + IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF, ui::SCALE_FACTOR_100P}, {"mediaplayerOverlayPlay", - IDR2_MEDIAPLAYER_OVERLAY_PLAY_BUTTON, + IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON, ui::SCALE_FACTOR_100P}, - {"panIcon", IDR2_PAN_SCROLL_ICON, ui::SCALE_FACTOR_100P}, - {"searchCancel", IDR2_SEARCH_CANCEL, ui::SCALE_FACTOR_100P}, - {"searchCancelPressed", IDR2_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P}, - {"searchMagnifier", IDR2_SEARCH_MAGNIFIER, ui::SCALE_FACTOR_100P}, + {"panIcon", IDR_PAN_SCROLL_ICON, ui::SCALE_FACTOR_100P}, + {"searchCancel", IDR_SEARCH_CANCEL, ui::SCALE_FACTOR_100P}, + {"searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED, ui::SCALE_FACTOR_100P}, + {"searchMagnifier", IDR_SEARCH_MAGNIFIER, ui::SCALE_FACTOR_100P}, {"searchMagnifierResults", - IDR2_SEARCH_MAGNIFIER_RESULTS, + IDR_SEARCH_MAGNIFIER_RESULTS, ui::SCALE_FACTOR_100P}, - {"textAreaResizeCorner", IDR2_TEXTAREA_RESIZER, ui::SCALE_FACTOR_100P}, - {"textAreaResizeCorner@2x", IDR2_TEXTAREA_RESIZER, ui::SCALE_FACTOR_200P}, - {"generatePassword", IDR2_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P}, + {"textAreaResizeCorner", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_100P}, + {"textAreaResizeCorner@2x", IDR_TEXTAREA_RESIZER, ui::SCALE_FACTOR_200P}, + {"generatePassword", IDR_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P}, {"generatePasswordHover", - IDR2_PASSWORD_GENERATION_ICON_HOVER, + IDR_PASSWORD_GENERATION_ICON_HOVER, ui::SCALE_FACTOR_100P}, {"html.css", IDR_UASTYLE_HTML_CSS, ui::SCALE_FACTOR_NONE}, {"quirks.css", IDR_UASTYLE_QUIRKS_CSS, ui::SCALE_FACTOR_NONE},
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index 013d1d5..eddd157 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -56,7 +56,6 @@ #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" #include "ipc/mojo/ipc_channel_mojo.h" -#include "ipc/mojo/scoped_ipc_support.h" #if defined(OS_WIN) #include "content/common/handle_enumerator_win.h" @@ -205,45 +204,6 @@ return ChildThreadImpl::current(); } -// Mojo client channel delegate to be used in single process mode. -class ChildThreadImpl::SingleProcessChannelDelegate - : public IPC::ChannelMojo::Delegate { - public: - explicit SingleProcessChannelDelegate( - scoped_refptr<base::SequencedTaskRunner> io_runner) - : io_runner_(io_runner), weak_factory_(this) {} - - ~SingleProcessChannelDelegate() override {} - - base::WeakPtr<IPC::ChannelMojo::Delegate> ToWeakPtr() override { - return weak_factory_.GetWeakPtr(); - } - - scoped_refptr<base::TaskRunner> GetIOTaskRunner() override { - return io_runner_; - } - - void OnChannelCreated(base::WeakPtr<IPC::ChannelMojo> channel) override {} - - void DeleteSoon() { - io_runner_->PostTask( - FROM_HERE, - base::Bind(&base::DeletePointer<SingleProcessChannelDelegate>, - base::Unretained(this))); - } - - private: - scoped_refptr<base::SequencedTaskRunner> io_runner_; - base::WeakPtrFactory<IPC::ChannelMojo::Delegate> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SingleProcessChannelDelegate); -}; - -void ChildThreadImpl::SingleProcessChannelDelegateDeleter::operator()( - SingleProcessChannelDelegate* delegate) const { - delegate->DeleteSoon(); -} - ChildThreadImpl::Options::Options() : channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kProcessChannelID)), @@ -321,15 +281,9 @@ VLOG(1) << "Mojo is enabled on child"; scoped_refptr<base::SequencedTaskRunner> io_task_runner = GetIOTaskRunner(); DCHECK(io_task_runner); - if (IsInBrowserProcess()) - single_process_channel_delegate_.reset( - new SingleProcessChannelDelegate(io_task_runner)); - ipc_support_.reset(new IPC::ScopedIPCSupport(io_task_runner)); - channel_->Init( - IPC::ChannelMojo::CreateClientFactory( - single_process_channel_delegate_.get(), - channel_name_), - create_pipe_now); + channel_->Init(IPC::ChannelMojo::CreateClientFactory( + nullptr, io_task_runner, channel_name_), + create_pipe_now); return; } @@ -401,8 +355,7 @@ channel_->AddFilter(bluetooth_message_filter_->GetFilter()); channel_->AddFilter(navigator_connect_dispatcher_->GetFilter()); - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kSingleProcess)) { + if (!IsInBrowserProcess()) { // In single process mode, browser-side tracing will cover the whole // process including renderers. channel_->AddFilter(new tracing::ChildTraceMessageFilter(
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index 7b04d42..821ca4e 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -235,15 +235,6 @@ void EnsureConnected(); - class SingleProcessChannelDelegate; - class SingleProcessChannelDelegateDeleter { - public: - void operator()(SingleProcessChannelDelegate* delegate) const; - }; - - scoped_ptr<IPC::ScopedIPCSupport> ipc_support_; - scoped_ptr<SingleProcessChannelDelegate, SingleProcessChannelDelegateDeleter> - single_process_channel_delegate_; scoped_ptr<MojoApplication> mojo_application_; std::string channel_name_;
diff --git a/content/child/scheduler/task_queue_manager.cc b/content/child/scheduler/task_queue_manager.cc index 386ebd0..826108c 100644 --- a/content/child/scheduler/task_queue_manager.cc +++ b/content/child/scheduler/task_queue_manager.cc
@@ -303,7 +303,6 @@ { base::AutoLock lock(lock_); - MoveReadyDelayedTasksToIncomingQueueLocked(lazy_now); if (!ShouldAutoPumpQueueLocked(previous_task)) return false; MoveReadyDelayedTasksToIncomingQueueLocked(lazy_now); @@ -464,6 +463,7 @@ time_source_(nullptr), disabled_by_default_tracing_category_( disabled_by_default_tracing_category), + deletion_sentinel_(new DeletionSentinel()), weak_factory_(this) { DCHECK(main_task_runner->RunsTasksOnCurrentThread()); TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, @@ -596,7 +596,9 @@ // Note that this function won't post another call to DoWork if one is // already pending, so it is safe to call it in a loop. MaybePostDoWorkOnMainRunner(); - ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); + + if (ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task)) + return; // The TaskQueueManager got deleted, we must bail out. if (!UpdateWorkQueues(&previous_task)) return; @@ -616,11 +618,12 @@ task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); } -void TaskQueueManager::ProcessTaskFromWorkQueue( +bool TaskQueueManager::ProcessTaskFromWorkQueue( size_t queue_index, bool has_previous_task, base::PendingTask* previous_task) { DCHECK(main_thread_checker_.CalledOnValidThread()); + scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); internal::TaskQueue* queue = Queue(queue_index); base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); if (!pending_task.nestable && main_task_runner_->IsNested()) { @@ -640,9 +643,16 @@ } task_annotator_.RunTask("TaskQueueManager::PostTask", "TaskQueueManager::RunTask", pending_task); + + // Detect if the TaskQueueManager just got deleted. If this happens we must + // not access any member variables after this point. + if (protect->HasOneRef()) + return true; + pending_task.task.Reset(); *previous_task = pending_task; } + return false; } bool TaskQueueManager::RunsTasksOnCurrentThread() const {
diff --git a/content/child/scheduler/task_queue_manager.h b/content/child/scheduler/task_queue_manager.h index e8563ee..861ea07 100644 --- a/content/child/scheduler/task_queue_manager.h +++ b/content/child/scheduler/task_queue_manager.h
@@ -128,6 +128,12 @@ friend class internal::LazyNow; friend class internal::TaskQueue; + class DeletionSentinel : public base::RefCounted<DeletionSentinel> { + private: + friend class base::RefCounted<DeletionSentinel>; + ~DeletionSentinel() {} + }; + // Called by the task queue to register a new pending task and allocate a // sequence number for it. void DidQueueTask(base::PendingTask* pending_task); @@ -158,7 +164,8 @@ // |queue_index|. If |has_previous_task| is true, |previous_task| should // contain the previous task in this work batch. Non-nestable task are // reposted on the run loop. The queue must not be empty. - void ProcessTaskFromWorkQueue(size_t queue_index, + // Returns true if the TaskQueueManager got deleted, and false otherwise. + bool ProcessTaskFromWorkQueue(size_t queue_index, bool has_previous_task, base::PendingTask* previous_task); @@ -198,6 +205,7 @@ const char* disabled_by_default_tracing_category_; + scoped_refptr<DeletionSentinel> deletion_sentinel_; base::WeakPtrFactory<TaskQueueManager> weak_factory_; DISALLOW_COPY_AND_ASSIGN(TaskQueueManager);
diff --git a/content/child/scheduler/task_queue_manager_unittest.cc b/content/child/scheduler/task_queue_manager_unittest.cc index 8fa5e29..b145b9e 100644 --- a/content/child/scheduler/task_queue_manager_unittest.cc +++ b/content/child/scheduler/task_queue_manager_unittest.cc
@@ -98,6 +98,11 @@ }; class TaskQueueManagerTest : public testing::Test { + public: + void DeleteTaskQueueManager() { + manager_.reset(); + } + protected: enum class SelectorType { Automatic, @@ -1036,5 +1041,19 @@ manager_->NextPendingDelayedTaskRunTime()); } +TEST_F(TaskQueueManagerTest, DeleteTaskQueueManagerInsideATask) { + Initialize(1u, SelectorType::Automatic); + + scoped_refptr<base::SingleThreadTaskRunner> runner = + manager_->TaskRunnerForQueue(0); + runner->PostTask(FROM_HERE, + base::Bind(&TaskQueueManagerTest::DeleteTaskQueueManager, + base::Unretained(this))); + + // This should not crash, assuming DoWork detects the TaskQueueManager has + // been deleted. + test_task_runner_->RunUntilIdle(); +} + } // namespace } // namespace content
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index e2cec70d..585d7f97 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -449,13 +449,6 @@ url = stream_override_->stream_url; } - // PlzNavigate: the only navigation requests going through the WebURLLoader - // are the ones created by CommitNavigation. - DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableBrowserSideNavigation) || - stream_override_.get() || - request.frameType() == WebURLRequest::FrameTypeNone); - if (CanHandleDataURLRequestLocally()) { if (sync_load_response) { // This is a sync load. Do the work now. @@ -470,6 +463,15 @@ return; } + // PlzNavigate: outside of tests, the only navigation requests going through + // the WebURLLoader are the ones created by CommitNavigation. Several browser + // tests load HTML directly through a data url which will be handled by the + // block above. + DCHECK_IMPLIES(base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation), + stream_override_.get() || + request.frameType() == WebURLRequest::FrameTypeNone); + GURL referrer_url( request.httpHeaderField(WebString::fromUTF8("Referer")).latin1()); const std::string& method = request.httpMethod().latin1();
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 8a4fb0c3..d609822 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -18,6 +18,7 @@ #include "content/public/common/context_menu_params.h" #include "content/public/common/frame_navigate_params.h" #include "content/public/common/javascript_message_type.h" +#include "content/public/common/message_port_types.h" #include "content/public/common/page_state.h" #include "content/public/common/resource_response.h" #include "content/public/common/transition_element.h" @@ -205,6 +206,37 @@ IPC_STRUCT_MEMBER(base::TimeTicks, ui_timestamp) IPC_STRUCT_END() +IPC_STRUCT_BEGIN(FrameMsg_PostMessage_Params) + // Whether the data format is supplied as serialized script value, or as + // a simple string. If it is a raw string, must be converted from string to a + // WebSerializedScriptValue in the renderer process. + IPC_STRUCT_MEMBER(bool, is_data_raw_string) + + // The serialized script value. + IPC_STRUCT_MEMBER(base::string16, data) + + // When sent to the browser, this is the routing ID of the source frame in + // the source process. The browser replaces it with the routing ID of the + // equivalent frame proxy in the destination process. + IPC_STRUCT_MEMBER(int, source_routing_id) + + // When sent from the browser, this is the routing ID of the source view in + // the destination process. This currently exists only to support legacy + // postMessage to Android WebView and will be removed once crbug.com/473258 + // is fixed. + IPC_STRUCT_MEMBER(int, source_view_routing_id) + + // The origin of the source frame. + IPC_STRUCT_MEMBER(base::string16, source_origin) + + // The origin for the message's target. + IPC_STRUCT_MEMBER(base::string16, target_origin) + + // Information about the MessagePorts this message contains. + IPC_STRUCT_MEMBER(std::vector<content::TransferredMessagePort>, message_ports) + IPC_STRUCT_MEMBER(std::vector<int>, new_routing_ids) +IPC_STRUCT_END() + IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams) IPC_STRUCT_TRAITS_MEMBER(url) IPC_STRUCT_TRAITS_MEMBER(referrer) @@ -508,6 +540,9 @@ IPC_MESSAGE_ROUTED1(FrameMsg_SetTextTrackSettings, FrameMsg_TextTrackSettings_Params /* params */) +// Posts a message from a frame in another process to the current renderer. +IPC_MESSAGE_ROUTED1(FrameMsg_PostMessageEvent, FrameMsg_PostMessage_Params) + #if defined(OS_ANDROID) // External popup menus. @@ -853,6 +888,11 @@ // out-of-process parent frame. IPC_MESSAGE_ROUTED0(FrameHostMsg_DispatchLoad) +// Sent to the browser from a frame proxy to post a message to the frame's +// active renderer. +IPC_MESSAGE_ROUTED1(FrameHostMsg_RouteMessageEvent, + FrameMsg_PostMessage_Params) + #if defined(OS_MACOSX) || defined(OS_ANDROID) // Message to show/hide a popup menu using native controls.
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.cc b/content/common/gpu/client/gpu_memory_buffer_impl.cc index b8284ec..53b9b29 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl.cc
@@ -85,6 +85,7 @@ case DXT1: case DXT5: case ETC1: + case R_8: case RGBA_8888: case RGBX_8888: case BGRA_8888: @@ -101,6 +102,7 @@ Format format, int plane, size_t* stride_in_bytes) { + base::CheckedNumeric<size_t> checked_stride = width; switch (format) { case ATCIA: case DXT5: @@ -111,26 +113,29 @@ case DXT1: case ETC1: DCHECK_EQ(plane, 0); - DCHECK_EQ(width % 2, 0U); + DCHECK_EQ(width % 2, 0u); *stride_in_bytes = width / 2; return true; - case RGBA_8888: - case RGBX_8888: - case BGRA_8888: { - base::CheckedNumeric<size_t> s = width; - DCHECK_EQ(plane, 0); - s *= 4; - if (!s.IsValid()) + case R_8: + checked_stride += 3; + if (!checked_stride.IsValid()) return false; - *stride_in_bytes = s.ValueOrDie(); + *stride_in_bytes = checked_stride.ValueOrDie() & ~0x3; return true; - } - case YUV_420: { + case RGBX_8888: + case RGBA_8888: + case BGRA_8888: + checked_stride *= 4; + if (!checked_stride.IsValid()) + return false; + *stride_in_bytes = checked_stride.ValueOrDie(); + return true; + case YUV_420: DCHECK_EQ(width % 2, 0u); *stride_in_bytes = width / SubsamplingFactor(format, plane); return true; - } } + NOTREACHED(); return false; } @@ -145,6 +150,7 @@ case DXT1: case DXT5: case ETC1: + case R_8: case RGBA_8888: case RGBX_8888: case BGRA_8888:
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc index 91552055..41696c6 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
@@ -127,6 +127,7 @@ case DXT1: case DXT5: case ETC1: + case R_8: case RGBA_8888: case BGRA_8888: case YUV_420: @@ -152,6 +153,7 @@ // Compressed images must have a width and height that's evenly divisible // by the block size. return size.width() % 4 == 0 && size.height() % 4 == 0; + case R_8: case RGBA_8888: case BGRA_8888: case RGBX_8888:
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc b/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc index 8ed95a9..7a0831de 100644 --- a/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc +++ b/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
@@ -21,6 +21,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::BGRA_8888: case gfx::GpuMemoryBuffer::YUV_420:
diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index 3d98e58..cb26cf21 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc
@@ -59,6 +59,8 @@ protected: ~GpuChannelManagerMessageFilter() override {} + // GPU IO thread bounces off GpuMsg_CreateGpuMemoryBuffer message, because + // the UI thread in the browser process must remain fast at all times. void OnCreateGpuMemoryBuffer( const GpuMsg_CreateGpuMemoryBuffer_Params& params) { TRACE_EVENT2("gpu",
diff --git a/content/common/gpu/gpu_memory_buffer_factory.h b/content/common/gpu/gpu_memory_buffer_factory.h index 467944b..5eb0dfc 100644 --- a/content/common/gpu/gpu_memory_buffer_factory.h +++ b/content/common/gpu/gpu_memory_buffer_factory.h
@@ -31,7 +31,6 @@ gfx::GpuMemoryBuffer::Usage usage; }; - GpuMemoryBufferFactory() {} virtual ~GpuMemoryBufferFactory() {} // Gets system supported GPU memory buffer factory types. Preferred type at @@ -47,7 +46,7 @@ std::vector<Configuration>* configurations) = 0; // Creates a new GPU memory buffer instance. A valid handle is returned on - // success. + // success. It can be called on any thread. virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer( gfx::GpuMemoryBufferId id, const gfx::Size& size, @@ -57,12 +56,16 @@ gfx::PluginWindowHandle surface_handle) = 0; // Destroys GPU memory buffer identified by |id|. + // It can be called on any thread. virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id) = 0; // Type-checking downcast routine. virtual gpu::ImageFactory* AsImageFactory() = 0; + protected: + GpuMemoryBufferFactory() {} + private: DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactory); };
diff --git a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc index 2737a4d..574b4f6 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
@@ -36,6 +36,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::YUV_420: @@ -56,6 +57,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::YUV_420:
diff --git a/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc b/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc index 992decd8..4c8f0e9 100644 --- a/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc +++ b/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc
@@ -23,10 +23,10 @@ GetSupportedGpuMemoryBufferConfigurations( std::vector<Configuration>* configurations) { const Configuration supported_configurations[] = { - { gfx::GpuMemoryBuffer::RGBA_8888, gfx::GpuMemoryBuffer::MAP }, - { gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::MAP }, - { gfx::GpuMemoryBuffer::YUV_420, gfx::GpuMemoryBuffer::MAP } - }; + {gfx::GpuMemoryBuffer::R_8, gfx::GpuMemoryBuffer::MAP}, + {gfx::GpuMemoryBuffer::RGBA_8888, gfx::GpuMemoryBuffer::MAP}, + {gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::MAP}, + {gfx::GpuMemoryBuffer::YUV_420, gfx::GpuMemoryBuffer::MAP}}; configurations->assign( supported_configurations, supported_configurations + arraysize(supported_configurations));
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 7312002..21498900 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h
@@ -166,6 +166,7 @@ IPC_STRUCT_TRAITS_MEMBER(driver_date) IPC_STRUCT_TRAITS_MEMBER(pixel_shader_version) IPC_STRUCT_TRAITS_MEMBER(vertex_shader_version) + IPC_STRUCT_TRAITS_MEMBER(max_msaa_samples) IPC_STRUCT_TRAITS_MEMBER(machine_model_name) IPC_STRUCT_TRAITS_MEMBER(machine_model_version) IPC_STRUCT_TRAITS_MEMBER(gl_version)
diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/content/common/gpu/media/vaapi_video_decode_accelerator.cc index 50a6a67..6b8e8791 100644 --- a/content/common/gpu/media/vaapi_video_decode_accelerator.cc +++ b/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -715,11 +715,11 @@ void VaapiVideoDecodeAccelerator::Cleanup() { DCHECK_EQ(message_loop_, base::MessageLoop::current()); + base::AutoLock auto_lock(lock_); if (state_ == kUninitialized || state_ == kDestroying) return; DVLOG(1) << "Destroying VAVDA"; - base::AutoLock auto_lock(lock_); state_ = kDestroying; client_ptr_factory_.reset();
diff --git a/content/common/gpu/media/vaapi_wrapper.cc b/content/common/gpu/media/vaapi_wrapper.cc index c267af5..01119d0 100644 --- a/content/common/gpu/media/vaapi_wrapper.cc +++ b/content/common/gpu/media/vaapi_wrapper.cc
@@ -291,10 +291,11 @@ #if defined(USE_X11) va_display_ = vaGetDisplay(gfx::GetXDisplay()); #elif defined(USE_OZONE) - ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); - ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); - - va_display_ = vaGetDisplayDRM(factory->GetDrmFd()); + const char* kDriRenderNode0Path = "/dev/dri/renderD128"; + drm_file_ = base::File(base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path), + base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_WRITE); + va_display_ = vaGetDisplayDRM(drm_file_.GetPlatformFile()); #endif // USE_X11 if (!vaDisplayIsValid(va_display_)) {
diff --git a/content/common/gpu/media/vaapi_wrapper.h b/content/common/gpu/media/vaapi_wrapper.h index 10eccd9..cb55afb 100644 --- a/content/common/gpu/media/vaapi_wrapper.h +++ b/content/common/gpu/media/vaapi_wrapper.h
@@ -13,6 +13,7 @@ #include <set> #include <vector> +#include "base/files/file.h" #include "base/lazy_instance.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" @@ -302,6 +303,11 @@ VAContextID va_vpp_context_id_; VABufferID va_vpp_buffer_id_; +#if defined(USE_OZONE) + // Drm file used to obtain access to the driver interface by VA. + base::File drm_file_; +#endif // USE_OZONE + // Singleton variable to store supported profile information for encode and // decode. static base::LazyInstance<LazyProfileInfos> profile_infos_;
diff --git a/content/common/indexed_db/indexed_db_key.cc b/content/common/indexed_db/indexed_db_key.cc index 1a3d72ec..c23d3e4 100644 --- a/content/common/indexed_db/indexed_db_key.cc +++ b/content/common/indexed_db/indexed_db_key.cc
@@ -5,7 +5,6 @@ #include "content/common/indexed_db/indexed_db_key.h" #include <string> -#include "base/logging.h" namespace content { @@ -56,18 +55,15 @@ IndexedDBKey::IndexedDBKey() : type_(WebIDBKeyTypeNull), - date_(0), - number_(0), size_estimate_(kOverheadSize) {} IndexedDBKey::IndexedDBKey(WebIDBKeyType type) - : type_(type), date_(0), number_(0), size_estimate_(kOverheadSize) { + : type_(type), size_estimate_(kOverheadSize) { DCHECK(type == WebIDBKeyTypeNull || type == WebIDBKeyTypeInvalid); } IndexedDBKey::IndexedDBKey(double number, WebIDBKeyType type) : type_(type), - date_(number), number_(number), size_estimate_(kOverheadSize + sizeof(number)) { DCHECK(type == WebIDBKeyTypeNumber || type == WebIDBKeyTypeDate); @@ -76,8 +72,6 @@ IndexedDBKey::IndexedDBKey(const KeyArray& array) : type_(WebIDBKeyTypeArray), array_(CopyKeyArray(array)), - date_(0), - number_(0), size_estimate_(kOverheadSize + CalculateArraySize(array)) {} IndexedDBKey::IndexedDBKey(const std::string& binary) @@ -137,7 +131,6 @@ case WebIDBKeyTypeString: return string_.compare(other.string_); case WebIDBKeyTypeDate: - return Compare(date_, other.date_); case WebIDBKeyTypeNumber: return Compare(number_, other.number_); case WebIDBKeyTypeInvalid:
diff --git a/content/common/indexed_db/indexed_db_key.h b/content/common/indexed_db/indexed_db_key.h index d9dfa1e..01227819 100644 --- a/content/common/indexed_db/indexed_db_key.h +++ b/content/common/indexed_db/indexed_db_key.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/logging.h" #include "base/memory/scoped_vector.h" #include "base/strings/string16.h" #include "content/common/content_export.h" @@ -41,11 +42,26 @@ bool Equals(const IndexedDBKey& other) const; blink::WebIDBKeyType type() const { return type_; } - const std::vector<IndexedDBKey>& array() const { return array_; } - const std::string& binary() const { return binary_; } - const base::string16& string() const { return string_; } - double date() const { return date_; } - double number() const { return number_; } + const std::vector<IndexedDBKey>& array() const { + DCHECK_EQ(type_, blink::WebIDBKeyTypeArray); + return array_; + } + const std::string& binary() const { + DCHECK_EQ(type_, blink::WebIDBKeyTypeBinary); + return binary_; + } + const base::string16& string() const { + DCHECK_EQ(type_, blink::WebIDBKeyTypeString); + return string_; + } + double date() const { + DCHECK_EQ(type_, blink::WebIDBKeyTypeDate); + return number_; + } + double number() const { + DCHECK_EQ(type_, blink::WebIDBKeyTypeNumber); + return number_; + } size_t size_estimate() const { return size_estimate_; } @@ -56,8 +72,7 @@ std::vector<IndexedDBKey> array_; std::string binary_; base::string16 string_; - double date_; - double number_; + double number_ = 0; size_t size_estimate_; };
diff --git a/content/common/indexed_db/indexed_db_key_range.cc b/content/common/indexed_db/indexed_db_key_range.cc index d061363..171365e4 100644 --- a/content/common/indexed_db/indexed_db_key_range.cc +++ b/content/common/indexed_db/indexed_db_key_range.cc
@@ -9,11 +9,7 @@ namespace content { -IndexedDBKeyRange::IndexedDBKeyRange() - : lower_(blink::WebIDBKeyTypeNull), - upper_(blink::WebIDBKeyTypeNull), - lower_open_(false), - upper_open_(false) {} +IndexedDBKeyRange::IndexedDBKeyRange() = default; IndexedDBKeyRange::IndexedDBKeyRange(const IndexedDBKey& lower, const IndexedDBKey& upper, @@ -25,7 +21,8 @@ upper_open_(upper_open) {} IndexedDBKeyRange::IndexedDBKeyRange(const IndexedDBKey& key) - : lower_(key), upper_(key), lower_open_(false), upper_open_(false) {} + : lower_(key), upper_(key) { +} IndexedDBKeyRange::IndexedDBKeyRange(const IndexedDBKeyRange& other) = default; IndexedDBKeyRange::~IndexedDBKeyRange() = default;
diff --git a/content/common/indexed_db/indexed_db_key_range.h b/content/common/indexed_db/indexed_db_key_range.h index 7dce7c6d..19a440b 100644 --- a/content/common/indexed_db/indexed_db_key_range.h +++ b/content/common/indexed_db/indexed_db_key_range.h
@@ -31,10 +31,10 @@ bool IsOnlyKey() const; private: - IndexedDBKey lower_; - IndexedDBKey upper_; - bool lower_open_; - bool upper_open_; + IndexedDBKey lower_ = IndexedDBKey(blink::WebIDBKeyTypeNull); + IndexedDBKey upper_ = IndexedDBKey(blink::WebIDBKeyTypeNull); + bool lower_open_ = false; + bool upper_open_ = false; }; } // namespace content
diff --git a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc index f47e703d..fe9a834 100644 --- a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc +++ b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
@@ -321,6 +321,7 @@ const std::vector<BrokerFilePermission>& permissions_extra) { static const char kDriRcPath[] = "/etc/drirc"; static const char kDriCard0Path[] = "/dev/dri/card0"; + static const char kDriRenderNode0Path[] = "/dev/dri/renderD128"; static const char kDevShm[] = "/dev/shm/"; CHECK(broker_process_ == NULL); @@ -328,6 +329,7 @@ // All GPU process policies need these files brokered out. std::vector<BrokerFilePermission> permissions; permissions.push_back(BrokerFilePermission::ReadWrite(kDriCard0Path)); + permissions.push_back(BrokerFilePermission::ReadWrite(kDriRenderNode0Path)); permissions.push_back(BrokerFilePermission::ReadOnly(kDriRcPath)); if (!IsChromeOS()) { permissions.push_back(
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index 0211a1c7..0a25bdc 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc
@@ -8,6 +8,7 @@ #include "base/base_switches.h" #include "base/command_line.h" +#include "base/debug/dump_without_crashing.h" #include "base/debug/profiler.h" #include "base/files/file_util.h" #include "base/hash.h" @@ -728,7 +729,6 @@ cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); DWORD last_error = ::GetLastError(); - policy->Release(); base::win::ScopedProcessInformation target(temp_process_info); TRACE_EVENT_END_ETW("StartProcessWithAccess::LAUNCHPROCESS", 0, 0); @@ -745,10 +745,18 @@ "Process.Sandbox.Lowbox.Launch.Error" : "Process.Sandbox.Launch.Error", last_error); + // Trigger a minidump without crashing the browser. + // Note that this function will only generate minidump if content host + // has already done pre-setup by calling + // base::debug::SetDumpWithoutCrashingFunction + base::debug::DumpWithoutCrashing(); } else DLOG(ERROR) << "Failed to launch process. Error: " << result; + + policy->Release(); return base::Process(); } + policy->Release(); if (delegate) delegate->PostSpawnTarget(target.process_handle());
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc index 3cb20a5..a89564d8 100644 --- a/content/common/swapped_out_messages.cc +++ b/content/common/swapped_out_messages.cc
@@ -31,7 +31,6 @@ case ViewHostMsg_DocumentDetached::ID: // Allow cross-process JavaScript calls. case ViewHostMsg_RouteCloseEvent::ID: - case ViewHostMsg_RouteMessageEvent::ID: // Handled by RenderFrameHost. case FrameHostMsg_BeforeUnload_ACK::ID: case FrameHostMsg_SwapOut_ACK::ID:
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 1a829f50..b8acc3ac 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -542,29 +542,6 @@ IPC_STRUCT_MEMBER(gfx::Size, max_size) IPC_STRUCT_END() -IPC_STRUCT_BEGIN(ViewMsg_PostMessage_Params) - // Whether the data format is supplied as serialized script value, or as - // a simple string. If it is a raw string, must be converted from string to a - // WebSerializedScriptValue in renderer. - IPC_STRUCT_MEMBER(bool, is_data_raw_string) - // The serialized script value. - IPC_STRUCT_MEMBER(base::string16, data) - // When sent to the browser, this is the routing ID of the source frame in - // the source process. The browser replaces it with the routing ID of the - // equivalent (swapped out) frame in the destination process. - IPC_STRUCT_MEMBER(int, source_routing_id) - - // The origin of the source frame. - IPC_STRUCT_MEMBER(base::string16, source_origin) - - // The origin for the message's target. - IPC_STRUCT_MEMBER(base::string16, target_origin) - - // Information about the MessagePorts this message contains. - IPC_STRUCT_MEMBER(std::vector<content::TransferredMessagePort>, message_ports) - IPC_STRUCT_MEMBER(std::vector<int>, new_routing_ids) -IPC_STRUCT_END() - // Messages sent from the browser to the renderer. #if defined(OS_ANDROID) @@ -718,10 +695,6 @@ gfx::Point, /* location */ blink::WebPluginAction) -// Posts a message from a frame in another process to the current renderer. -IPC_MESSAGE_ROUTED1(ViewMsg_PostMessageEvent, - ViewMsg_PostMessage_Params) - // Resets the page scale for the current main frame to the default page scale. IPC_MESSAGE_ROUTED0(ViewMsg_ResetPageScale) @@ -1293,11 +1266,6 @@ // renderer, instructing it to close. IPC_MESSAGE_ROUTED0(ViewHostMsg_RouteCloseEvent) -// Sent to the browser from an inactive renderer to post a message to the -// active renderer. -IPC_MESSAGE_ROUTED1(ViewHostMsg_RouteMessageEvent, - ViewMsg_PostMessage_Params) - // Notifies that the preferred size of the content changed. IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredSizeChange, gfx::Size /* pref_size */)
diff --git a/content/content.gyp b/content/content.gyp index a5d4829c..f95cb90e 100644 --- a/content/content.gyp +++ b/content/content.gyp
@@ -449,6 +449,7 @@ 'navigation_controller_java', 'popup_item_type_java', 'result_codes_java', + 'readback_response_java', 'speech_recognition_error_java', 'top_controls_state_java', 'screen_orientation_values_java', @@ -522,6 +523,14 @@ 'includes': [ '../build/android/java_cpp_enum.gypi' ], }, { + 'target_name': 'readback_response_java', + 'type': 'none', + 'variables': { + 'source_file': 'public/browser/readback_types.h', + }, + 'includes': [ '../build/android/java_cpp_enum.gypi' ], + }, + { 'target_name': 'result_codes_java', 'type': 'none', 'variables': {
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index b35ed8f..5491340 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi
@@ -626,8 +626,6 @@ 'renderer/media/media_stream_video_source.h', 'renderer/media/media_stream_video_track.cc', 'renderer/media/media_stream_video_track.h', - 'renderer/media/native_handle_impl.cc', - 'renderer/media/native_handle_impl.h', 'renderer/media/peer_connection_identity_service.cc', 'renderer/media/peer_connection_identity_service.h', 'renderer/media/peer_connection_tracker.cc',
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index a2dbd10..fdcab25 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -113,6 +113,7 @@ "//content/browser/gamepad/gamepad_standard_mappings.h", "//content/public/browser/invalidate_type.h", "//content/public/browser/navigation_controller.h", + "//content/public/browser/readback_types.h", "//content/public/common/console_message_level.h", "//content/public/common/result_codes.h", "//content/public/common/screen_orientation_values.h", @@ -127,6 +128,7 @@ "org/chromium/content_public/browser/InvalidateTypes.java", "org/chromium/content_public/browser/navigation_controller/LoadURLType.java", "org/chromium/content_public/browser/navigation_controller/UserAgentOverrideOption.java", + "org/chromium/content_public/browser/readback_types/ReadbackResponse.java", "org/chromium/content_public/common/ConsoleMessageLevel.java", "org/chromium/content_public/common/ResultCode.java", "org/chromium/content_public/common/ScreenOrientationValues.java",
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java index fae9a41..d25ac652 100644 --- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java +++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -126,7 +126,7 @@ public void onCreate() { Log.i(TAG, "Creating new ChildProcessService pid=" + Process.myPid()); if (sContext.get() != null) { - Log.e(TAG, "ChildProcessService created again in process!"); + throw new RuntimeException("Illegal child process reuse."); } sContext.set(this); super.onCreate();
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java index a84e44f..291966d 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentReadbackHandler.java
@@ -11,6 +11,7 @@ import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; import org.chromium.base.ThreadUtils; +import org.chromium.content_public.browser.readback_types.ReadbackResponse; import org.chromium.ui.base.WindowAndroid; /** @@ -27,7 +28,7 @@ * @param bitmap The {@link Bitmap} of the content. Null will be passed for readback * failure. */ - public void onFinishGetBitmap(Bitmap bitmap); + public void onFinishGetBitmap(Bitmap bitmap, int response); } private int mNextReadbackId = 1; @@ -59,11 +60,11 @@ @CalledByNative - private void notifyGetBitmapFinished(int readbackId, Bitmap bitmap) { + private void notifyGetBitmapFinished(int readbackId, Bitmap bitmap, int response) { GetBitmapCallback callback = mGetBitmapRequests.get(readbackId); if (callback != null) { mGetBitmapRequests.delete(readbackId); - callback.onFinishGetBitmap(bitmap); + callback.onFinishGetBitmap(bitmap, response); } else { // readback Id is unregistered. assert false : "Readback finished for unregistered Id: " + readbackId; @@ -84,7 +85,7 @@ public void getContentBitmapAsync(float scale, Rect srcRect, ContentViewCore view, Bitmap.Config config, GetBitmapCallback callback) { if (!readyForReadback()) { - callback.onFinishGetBitmap(null); + callback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE); return; } ThreadUtils.assertOnUiThread(); @@ -104,7 +105,7 @@ */ public void getCompositorBitmapAsync(WindowAndroid windowAndroid, GetBitmapCallback callback) { if (!readyForReadback()) { - callback.onFinishGetBitmap(null); + callback.onFinishGetBitmap(null, ReadbackResponse.SURFACE_UNAVAILABLE); return; } ThreadUtils.assertOnUiThread();
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index 46d3c7d..3dc0d71 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -82,7 +82,6 @@ import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.ui.base.DeviceFormFactor; -import org.chromium.ui.base.ViewAndroid; import org.chromium.ui.base.ViewAndroidDelegate; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.ime.TextInputType; @@ -588,8 +587,6 @@ // onNativeFlingStopped() is called asynchronously. private int mPotentiallyActiveFlingCount; - private ViewAndroid mViewAndroid; - private SmartClipDataListener mSmartClipDataListener = null; private ObserverList<ContainerViewObserver> mContainerViewObservers; @@ -749,11 +746,6 @@ return mInputConnection; } - @VisibleForTesting - ViewAndroid getViewAndroid() { - return mViewAndroid; - } - private ImeAdapter createImeAdapter() { return new ImeAdapter(mInputMethodManagerWrapper, new ImeAdapter.ImeAdapterDelegate() { @@ -832,12 +824,11 @@ setContainerView(containerView); long windowNativePointer = windowAndroid.getNativePointer(); assert windowNativePointer != 0; - createViewAndroid(windowAndroid); mZoomControlsDelegate = NO_OP_ZOOM_CONTROLS_DELEGATE; mNativeContentViewCore = nativeInit( - webContents, mViewAndroid, windowNativePointer, mRetainedJavaScriptObjects); + webContents, mViewAndroidDelegate, windowNativePointer, mRetainedJavaScriptObjects); mWebContents = nativeGetWebContentsAndroid(mNativeContentViewCore); setContainerViewInternals(internalDispatcher); @@ -857,11 +848,6 @@ new ContentViewAndroidDelegate(mContext, mContainerView, mRenderCoordinates); } - @VisibleForTesting - void createViewAndroid(WindowAndroid windowAndroid) { - mViewAndroid = new ViewAndroid(mViewAndroidDelegate); - } - /** * Sets a new container view for this {@link ContentViewCore}. * @@ -3124,7 +3110,7 @@ if (potentiallyActiveFlingCount > 0) updateGestureStateListener(GestureEventType.FLING_END); } - private native long nativeInit(WebContents webContents, ViewAndroid viewAndroid, + private native long nativeInit(WebContents webContents, ViewAndroidDelegate viewAndroidDelegate, long windowAndroidPtr, HashSet<Object> retainedObjectSet); private static native ContentViewCore nativeFromWebContentsAndroid(WebContents webContents); ContentVideoViewClient getContentVideoViewClient() {
diff --git a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java b/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java index 3c561c3..4eea4c0c3 100644 --- a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java +++ b/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
@@ -4,17 +4,45 @@ package org.chromium.content.browser; -import org.chromium.base.CalledByNative; -import org.chromium.ui.base.ViewAndroid; +import android.view.View; +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; +import org.chromium.ui.base.ViewAndroidDelegate; + +import java.lang.ref.WeakReference; + +@JNINamespace("content") class PowerSaveBlocker { + // WeakReference to prevent leaks in Android WebView. + private WeakReference<View> mKeepScreenOnView; + @CalledByNative - private static void applyBlock(ViewAndroid view) { - view.incrementKeepScreenOnCount(); + private static PowerSaveBlocker create() { + return new PowerSaveBlocker(); + } + + private PowerSaveBlocker() {} + + @CalledByNative + private void applyBlock(ContentViewCore contentViewCore) { + assert mKeepScreenOnView == null; + ViewAndroidDelegate delegate = contentViewCore.getViewAndroidDelegate(); + View anchorView = delegate.acquireAnchorView(); + mKeepScreenOnView = new WeakReference<>(anchorView); + delegate.setAnchorViewPosition(anchorView, 0, 0, 0, 0); + anchorView.setKeepScreenOn(true); } @CalledByNative - private static void removeBlock(ViewAndroid view) { - view.decrementKeepScreenOnCount(); + private void removeBlock(ContentViewCore contentViewCore) { + assert mKeepScreenOnView != null; + View anchorView = mKeepScreenOnView.get(); + mKeepScreenOnView = null; + if (anchorView == null) return; + + ViewAndroidDelegate delegate = contentViewCore.getViewAndroidDelegate(); + anchorView.setKeepScreenOn(false); + delegate.releaseAnchorView(anchorView); } }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreViewAndroidDelegateTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreViewAndroidDelegateTest.java index f803f9a..fd1bbb1 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreViewAndroidDelegateTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreViewAndroidDelegateTest.java
@@ -12,7 +12,6 @@ import org.chromium.content_shell_apk.ContentShellTestBase; import org.chromium.ui.base.ViewAndroidDelegate; -import org.chromium.ui.base.WindowAndroid; /** * This suite verifies that when {@link ContentViewCore} replaces container @@ -43,14 +42,6 @@ } @SmallTest - public void testViewAndroidCreatedWithCorrectDelegate() { - mContentViewCore.createViewAndroid( - new WindowAndroid(getActivity().getApplicationContext())); - assertSame(mViewAndroidDelegate, - mContentViewCore.getViewAndroid().getViewAndroidDelegate()); - } - - @SmallTest public void testAddAndRemoveAnchorViews() { assertEquals(0, mContainerView.getChildCount());
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewReadbackTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewReadbackTest.java index 03b3885..5a670c4 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewReadbackTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewReadbackTest.java
@@ -105,7 +105,7 @@ GetBitmapCallback callback = new GetBitmapCallback() { @Override - public void onFinishGetBitmap(Bitmap bitmap) { + public void onFinishGetBitmap(Bitmap bitmap, int response) { assertNotNull("Readback did not return valid bitmap", bitmap); // Verify a pixel in the center of the screenshot. color.set(bitmap.getPixel(bitmap.getWidth() / 2, bitmap.getHeight() / 2));
diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h index f64f672..e528090 100644 --- a/content/public/browser/android/content_view_core.h +++ b/content/public/browser/android/content_view_core.h
@@ -45,6 +45,8 @@ static ContentViewCore* GetNativeContentViewCore(JNIEnv* env, jobject obj); virtual WebContents* GetWebContents() const = 0; + + // May return null reference. virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0; virtual ui::ViewAndroid* GetViewAndroid() const = 0; virtual ui::WindowAndroid* GetWindowAndroid() const = 0;
diff --git a/content/public/browser/devtools_frontend_host.h b/content/public/browser/devtools_frontend_host.h index 5eb2a90..c00f111 100644 --- a/content/public/browser/devtools_frontend_host.h +++ b/content/public/browser/devtools_frontend_host.h
@@ -42,6 +42,8 @@ Delegate* delegate); CONTENT_EXPORT virtual ~DevToolsFrontendHost() {} + + CONTENT_EXPORT virtual void BadMessageRecieved() {} }; } // namespace content
diff --git a/content/public/browser/readback_types.h b/content/public/browser/readback_types.h index 338dc38..6c7e314 100644 --- a/content/public/browser/readback_types.h +++ b/content/public/browser/readback_types.h
@@ -11,6 +11,12 @@ namespace content { +// ReadbackResponse type used in ContentReadbackHandler. +// +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: ( +// org.chromium.content_public.browser.readback_types) +// GENERATED_JAVA_PREFIX_TO_STRIP: READBACK_ enum ReadbackResponse { READBACK_SUCCESS, READBACK_FAILED,
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index c8e488d..935b219 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -125,7 +125,9 @@ std::string url_str = "data:text/html;charset=utf-8,"; url_str.append(html); GURL url(url_str); - GetMainFrame()->loadRequest(WebURLRequest(url)); + WebURLRequest request(url); + request.setCheckForBrowserSideNavigation(false); + GetMainFrame()->loadRequest(request); // The load actually happens asynchronously, so we pump messages to process // the pending continuation. FrameLoadWaiter(view_->GetMainRenderFrame()).Wait();
diff --git a/content/renderer/media/OWNERS b/content/renderer/media/OWNERS index dbaad20..4f06210 100644 --- a/content/renderer/media/OWNERS +++ b/content/renderer/media/OWNERS
@@ -10,10 +10,10 @@ perkj@chromium.org tommi@chromium.org +# Cast Streaming OWNERS. per-file cast_*=hclam@chromium.org per-file cast_*=hubbe@chromium.org -per-file cast_*=mikhal@chromium.org -per-file cast_*=pwestin@google.com +per-file cast_*=miu@chromium.org per-file midi_*=toyoshim@chromium.org per-file renderer_webmidi*=toyoshim@chromium.org
diff --git a/content/renderer/media/crypto/render_cdm_factory.cc b/content/renderer/media/crypto/render_cdm_factory.cc index fab62f90..c871f9c 100644 --- a/content/renderer/media/crypto/render_cdm_factory.cc +++ b/content/renderer/media/crypto/render_cdm_factory.cc
@@ -48,18 +48,18 @@ const media::SessionKeysChangeCB& session_keys_change_cb, const media::SessionExpirationUpdateCB& session_expiration_update_cb) { DCHECK(thread_checker_.CalledOnValidThread()); - // TODO(jrummell): Pass |security_origin| to all constructors. - // TODO(jrummell): Enable the following line once blink code updated to - // check the security origin before calling. - // DCHECK(security_origin.is_valid()); + + if (!security_origin.is_valid()) + return nullptr; if (media::CanUseAesDecryptor(key_system)) { // TODO(sandersd): Currently the prefixed API always allows distinctive // identifiers and persistent state. Once that changes we can sanity check // here that neither is allowed for AesDecryptor, since it does not support // them and should never be configured that way. http://crbug.com/455271 - return scoped_ptr<media::MediaKeys>(new media::AesDecryptor( - session_message_cb, session_closed_cb, session_keys_change_cb)); + return scoped_ptr<media::MediaKeys>( + new media::AesDecryptor(security_origin, session_message_cb, + session_closed_cb, session_keys_change_cb)); } #if defined(ENABLE_PEPPER_CDMS)
diff --git a/content/renderer/media/native_handle_impl.cc b/content/renderer/media/native_handle_impl.cc deleted file mode 100644 index 3988e393..0000000 --- a/content/renderer/media/native_handle_impl.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/native_handle_impl.h" - -namespace content { - -NativeHandleImpl::NativeHandleImpl(scoped_refptr<media::VideoFrame> frame) - : frame_(frame) {} - -NativeHandleImpl::~NativeHandleImpl() {} - -void* NativeHandleImpl::GetHandle() { return frame_.get(); } - -} // namespace content
diff --git a/content/renderer/media/native_handle_impl.h b/content/renderer/media/native_handle_impl.h deleted file mode 100644 index 20a4f03..0000000 --- a/content/renderer/media/native_handle_impl.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_NATIVE_HANDLE_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_NATIVE_HANDLE_IMPL_H_ - -#include "base/memory/ref_counted.h" -#include "media/base/video_frame.h" -#include "third_party/webrtc/common_video/interface/native_handle.h" - -namespace content { - -class NativeHandleImpl : public webrtc::NativeHandle { - public: - // Wraps a video frame in the handle. - explicit NativeHandleImpl(scoped_refptr<media::VideoFrame> frame); - ~NativeHandleImpl() override; - - // Retrieves the video frame in the handle. The frame is still ref-counted by - // the handle. The ref count decreases when NativeHandleImpl is destroyed. - void* GetHandle() override; - - private: - scoped_refptr<media::VideoFrame> frame_; - - DISALLOW_COPY_AND_ASSIGN(NativeHandleImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_NATIVE_HANDLE_IMPL_H_
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc index 66ef3497..74c85e5 100644 --- a/content/renderer/media/rtc_video_decoder.cc +++ b/content/renderer/media/rtc_video_decoder.cc
@@ -13,13 +13,16 @@ #include "base/stl_util.h" #include "base/synchronization/waitable_event.h" #include "base/task_runner_util.h" -#include "content/renderer/media/native_handle_impl.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "media/base/bind_to_current_loop.h" #include "media/renderers/gpu_video_accelerator_factories.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/webrtc/common_video/interface/i420_video_frame.h" +#include "third_party/webrtc/base/bind.h" #include "third_party/webrtc/system_wrappers/interface/ref_count.h" +#include "third_party/webrtc/video_frame.h" + +static void ReleaseFrame(scoped_refptr<media::VideoFrame> frame) { +} namespace content { @@ -388,13 +391,13 @@ DCHECK(inserted); // Create a WebRTC video frame. - webrtc::RefCountImpl<NativeHandleImpl>* handle = - new webrtc::RefCountImpl<NativeHandleImpl>(frame); - webrtc::I420VideoFrame decoded_image(handle, + webrtc::I420VideoFrame decoded_image(frame.get(), picture.visible_rect().width(), picture.visible_rect().height(), timestamp, - 0); + 0, + webrtc::kVideoRotation_0, + rtc::Bind(&ReleaseFrame, frame)); // Invoke decode callback. WebRTC expects no callback after Reset or Release. {
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/content/renderer/media/webrtc/media_stream_remote_video_source.cc index e3b2c4d..a151647 100644 --- a/content/renderer/media/webrtc/media_stream_remote_video_source.cc +++ b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -10,7 +10,6 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/threading/thread_checker.h" #include "base/trace_event/trace_event.h" -#include "content/renderer/media/native_handle_impl.h" #include "content/renderer/media/webrtc/track_observer.h" #include "media/base/bind_to_current_loop.h" #include "media/base/video_frame.h" @@ -71,9 +70,8 @@ scoped_refptr<media::VideoFrame> video_frame; if (incoming_frame->GetNativeHandle() != NULL) { - NativeHandleImpl* handle = - static_cast<NativeHandleImpl*>(incoming_frame->GetNativeHandle()); - video_frame = static_cast<media::VideoFrame*>(handle->GetHandle()); + video_frame = + static_cast<media::VideoFrame*>(incoming_frame->GetNativeHandle()); video_frame->set_timestamp(timestamp); } else { const cricket::VideoFrame* frame =
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc index 024c2b1e..370de9a 100644 --- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc +++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -65,9 +65,7 @@ return frame_->stride(WebRtcToMediaPlaneType(type)); } - rtc::scoped_refptr<webrtc::NativeHandle> native_handle() const override { - return nullptr; - } + void* native_handle() const override { return nullptr; } ~VideoFrameWrapper() override {} friend class rtc::RefCountedObject<VideoFrameWrapper>;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 8915dea..38e058a 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -125,6 +125,7 @@ #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebFrameWidget.h" #include "third_party/WebKit/public/web/WebGlyphCache.h" +#include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" #include "third_party/WebKit/public/web/WebNavigationPolicy.h" @@ -137,6 +138,7 @@ #include "third_party/WebKit/public/web/WebSearchableFormData.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" +#include "third_party/WebKit/public/web/WebSerializedScriptValue.h" #include "third_party/WebKit/public/web/WebSettings.h" #include "third_party/WebKit/public/web/WebSurroundingText.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" @@ -186,6 +188,8 @@ using blink::WebData; using blink::WebDataSource; using blink::WebDocument; +using blink::WebDOMEvent; +using blink::WebDOMMessageEvent; using blink::WebElement; using blink::WebExternalPopupMenu; using blink::WebExternalPopupMenuClient; @@ -206,6 +210,7 @@ using blink::WebSearchableFormData; using blink::WebSecurityOrigin; using blink::WebSecurityPolicy; +using blink::WebSerializedScriptValue; using blink::WebServiceWorkerProvider; using blink::WebStorageQuotaCallbacks; using blink::WebString; @@ -1049,6 +1054,7 @@ IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateSandboxFlags, OnDidUpdateSandboxFlags) IPC_MESSAGE_HANDLER(FrameMsg_SetTextTrackSettings, OnTextTrackSettingsChanged) + IPC_MESSAGE_HANDLER(FrameMsg_PostMessageEvent, OnPostMessageEvent) #if defined(OS_ANDROID) IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems) #elif defined(OS_MACOSX) @@ -1064,6 +1070,8 @@ const CommonNavigationParams& common_params, const StartNavigationParams& start_params, const RequestNavigationParams& request_params) { + DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation)); TRACE_EVENT2("navigation", "RenderFrameImpl::OnNavigate", "id", routing_id_, "url", common_params.url.possibly_invalid_spec()); @@ -1261,6 +1269,12 @@ render_view_->SetSwappedOut(true); is_swapped_out_ = true; + // Set the proxy here, since OnStop() below could cause an onload event + // handler to execute, which could trigger code such as + // willCheckAndDispatchMessageEvent() that needs the proxy. + if (proxy) + set_render_frame_proxy(proxy); + // Now that we're swapped out and filtering IPC messages, stop loading to // ensure that no other in-progress navigation continues. We do this here // to avoid sending a DidStopLoading message to the browser process. @@ -1310,8 +1324,6 @@ // TODO(nasko): delete the frame here, since we've replaced it with a // proxy. } - } else { - set_render_frame_proxy(proxy); } } @@ -1602,6 +1614,77 @@ WebString::fromUTF8(params.text_track_text_size)); } +void RenderFrameImpl::OnPostMessageEvent( + const FrameMsg_PostMessage_Params& params) { + // Find the source frame if it exists. + WebFrame* source_frame = NULL; + if (params.source_view_routing_id != MSG_ROUTING_NONE) { + // Support a legacy postMessage path for specifying a source RenderView; + // this is currently used when sending messages to Android WebView. + // TODO(alexmos): This path can be removed once crbug.com/473258 is fixed. + RenderViewImpl* source_view = + RenderViewImpl::FromRoutingID(params.source_view_routing_id); + if (source_view) + source_frame = source_view->webview()->mainFrame(); + } else if (params.source_routing_id != MSG_ROUTING_NONE) { + RenderFrameProxy* source_proxy = + RenderFrameProxy::FromRoutingID(params.source_routing_id); + if (source_proxy) { + // Currently, navigating a top-level frame cross-process does not swap + // the WebLocalFrame for a WebRemoteFrame in the frame tree, and the + // WebRemoteFrame will not have an associated blink::Frame. If this is + // the case for |source_proxy|, use the corresponding (swapped-out) + // WebLocalFrame instead, so that event.source for this message can be + // set and used properly. + if (source_proxy->IsMainFrameDetachedFromTree()) + source_frame = source_proxy->render_view()->webview()->mainFrame(); + else + source_frame = source_proxy->web_frame(); + } + } + + // If the message contained MessagePorts, create the corresponding endpoints. + blink::WebMessagePortChannelArray channels = + WebMessagePortChannelImpl::CreatePorts( + params.message_ports, params.new_routing_ids, + base::MessageLoopProxy::current().get()); + + WebSerializedScriptValue serialized_script_value; + if (params.is_data_raw_string) { + v8::HandleScope handle_scope(blink::mainThreadIsolate()); + v8::Local<v8::Context> context = frame_->mainWorldScriptContext(); + v8::Context::Scope context_scope(context); + V8ValueConverterImpl converter; + converter.SetDateAllowed(true); + converter.SetRegExpAllowed(true); + scoped_ptr<base::Value> value(new base::StringValue(params.data)); + v8::Handle<v8::Value> result_value = converter.ToV8Value(value.get(), + context); + serialized_script_value = WebSerializedScriptValue::serialize(result_value); + } else { + serialized_script_value = WebSerializedScriptValue::fromString(params.data); + } + + // Create an event with the message. The next-to-last parameter to + // initMessageEvent is the last event ID, which is not used with postMessage. + WebDOMEvent event = frame_->document().createEvent("MessageEvent"); + WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>(); + msg_event.initMessageEvent("message", + // |canBubble| and |cancellable| are always false + false, false, + serialized_script_value, + params.source_origin, source_frame, "", channels); + + // We must pass in the target_origin to do the security check on this side, + // since it may have changed since the original postMessage call was made. + WebSecurityOrigin target_origin; + if (!params.target_origin.empty()) { + target_origin = + WebSecurityOrigin::createFromString(WebString(params.target_origin)); + } + frame_->dispatchMessageEventWithOriginCheck(target_origin, msg_event); +} + #if defined(OS_ANDROID) void RenderFrameImpl::OnSelectPopupMenuItems( bool canceled, @@ -3562,31 +3645,23 @@ blink::WebDOMMessageEvent event) { DCHECK(!frame_ || frame_ == target_frame); + // Currently, a postMessage that targets a cross-process frame can be plumbed + // either through this function or RenderFrameProxy::postMessageEvent. This + // function is used when the target cross-process frame is a top-level frame + // which has been swapped out. In that case, the corresponding WebLocalFrame + // currently remains in the frame tree even in site-per-process mode (see + // OnSwapOut). RenderFrameProxy::postMessageEvent is used in + // --site-per-process mode for all other cases. + // + // TODO(alexmos, nasko): When swapped-out:// disappears, this should be + // cleaned up so that RenderFrameProxy::postMessageEvent is the only path for + // cross-process postMessages. if (!is_swapped_out_) return false; - ViewMsg_PostMessage_Params params; - params.is_data_raw_string = false; - params.data = event.data().toString(); - params.source_origin = event.origin(); - if (!target_origin.isNull()) - params.target_origin = target_origin.toString(); - - params.message_ports = - WebMessagePortChannelImpl::ExtractMessagePortIDs(event.releaseChannels()); - - // Include the routing ID for the source frame (if one exists), which the - // browser process will translate into the routing ID for the equivalent - // frame in the target process. - params.source_routing_id = MSG_ROUTING_NONE; - if (source_frame) { - RenderViewImpl* source_view = - RenderViewImpl::FromWebView(source_frame->view()); - if (source_view) - params.source_routing_id = source_view->routing_id(); - } - - Send(new ViewHostMsg_RouteMessageEvent(render_view_->routing_id_, params)); + CHECK(render_frame_proxy_); + render_frame_proxy_->postMessageEvent( + source_frame, render_frame_proxy_->web_frame(), target_origin, event); return true; }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 47c9620..b08a73c 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -44,6 +44,7 @@ class TransportDIB; struct FrameHostMsg_AddNavigationTransitionData_Params; struct FrameMsg_NewFrame_WidgetParams; +struct FrameMsg_PostMessage_Params; struct FrameMsg_TextTrackSettings_Params; namespace blink { @@ -564,6 +565,7 @@ private: friend class RenderFrameImplTest; friend class RenderFrameObserver; + friend class RenderViewImplTest; friend class RendererAccessibilityTest; FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuDisplayNoneTest, SelectItem); FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange); @@ -645,6 +647,7 @@ void OnDidUpdateSandboxFlags(SandboxFlags flags); void OnTextTrackSettingsChanged( const FrameMsg_TextTrackSettings_Params& params); + void OnPostMessageEvent(const FrameMsg_PostMessage_Params& params); #if defined(OS_ANDROID) void OnSelectPopupMenuItems(bool canceled, const std::vector<int>& selected_indices);
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 1523fb73..f433733 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -323,7 +323,7 @@ blink::WebDOMMessageEvent event) { DCHECK(!web_frame_ || web_frame_ == target_frame); - ViewMsg_PostMessage_Params params; + FrameMsg_PostMessage_Params params; params.is_data_raw_string = false; params.data = event.data().toString(); params.source_origin = event.origin(); @@ -338,13 +338,14 @@ // frame in the target process. params.source_routing_id = MSG_ROUTING_NONE; if (source_frame) { - RenderViewImpl* source_view = - RenderViewImpl::FromWebView(source_frame->view()); - if (source_view) - params.source_routing_id = source_view->routing_id(); + RenderFrameImpl* source_render_frame = + RenderFrameImpl::FromWebFrame(source_frame); + if (source_render_frame) + params.source_routing_id = source_render_frame->GetRoutingID(); } + params.source_view_routing_id = MSG_ROUTING_NONE; - Send(new ViewHostMsg_RouteMessageEvent(render_view_->GetRoutingID(), params)); + Send(new FrameHostMsg_RouteMessageEvent(routing_id_, params)); } void RenderFrameProxy::initializeChildFrame(
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 65352cf..19a94f68 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -100,6 +100,12 @@ // RenderFrameProxy's WebRemoteFrame. void SetReplicatedState(const FrameReplicationState& state); + // Navigating a top-level frame cross-process does not swap the WebLocalFrame + // for a WebRemoteFrame in the frame tree. In this case, this WebRemoteFrame + // is not attached to the frame tree and there is no blink::Frame associated + // with it, so it is not in state where most operations on it will succeed. + bool IsMainFrameDetachedFromTree() const; + int routing_id() { return routing_id_; } RenderViewImpl* render_view() { return render_view_; } blink::WebRemoteFrame* web_frame() { return web_frame_; } @@ -126,12 +132,6 @@ void Init(blink::WebRemoteFrame* frame, RenderViewImpl* render_view); - // Navigating a top-level frame cross-process does not swap the WebLocalFrame - // for a WebRemoteFrame in the frame tree. In this case, this WebRemoteFrame - // is not attached to the frame tree and there is no blink::Frame associated - // with it, so it is not in state where most operations on it will succeed. - bool IsMainFrameDetachedFromTree() const; - // IPC::Listener bool OnMessageReceived(const IPC::Message& msg) override;
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 164feec..839265c 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -285,6 +285,19 @@ view()->OnSetZoomLevelForView(false, level); } + void NavigateFrame(const CommonNavigationParams& common_params, + const StartNavigationParams& start_params, + const RequestNavigationParams& request_params) { + // PlzNavigate + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableBrowserSideNavigation)) { + frame()->OnCommitNavigation(ResourceResponseHead(), common_params.url, + common_params, request_params); + return; + } + frame()->OnNavigate(common_params, start_params, request_params); + } + private: scoped_ptr<MockKeyboard> mock_keyboard_; }; @@ -432,7 +445,7 @@ start_params.is_post = true; start_params.browser_initiated_post_data = post_data; - frame()->OnNavigate(common_params, start_params, request_params); + NavigateFrame(common_params, start_params, request_params); ProcessPendingMessages(); const IPC::Message* frame_navigate_msg = @@ -633,7 +646,7 @@ request_params.current_history_list_offset = 0; request_params.pending_history_list_offset = 1; request_params.page_id = -1; - frame()->OnNavigate(common_params, StartNavigationParams(), request_params); + NavigateFrame(common_params, StartNavigationParams(), request_params); ProcessPendingMessages(); const IPC::Message* msg3 = render_thread_->sink().GetUniqueMessageMatching( ViewHostMsg_UpdateState::ID); @@ -671,8 +684,7 @@ request_params_A.pending_history_list_offset = 0; request_params_A.page_id = 1; request_params_A.page_state = state_A; - frame()->OnNavigate(common_params_A, StartNavigationParams(), - request_params_A); + NavigateFrame(common_params_A, StartNavigationParams(), request_params_A); EXPECT_EQ(1, view()->historyBackListCount()); EXPECT_EQ(2, view()->historyBackListCount() + view()->historyForwardListCount() + 1); @@ -702,7 +714,7 @@ request_params.pending_history_list_offset = 0; request_params.page_id = 1; request_params.page_state = state_A; - frame()->OnNavigate(common_params, StartNavigationParams(), request_params); + NavigateFrame(common_params, StartNavigationParams(), request_params); ProcessPendingMessages(); // Verify page A committed, not swappedout://. @@ -820,8 +832,7 @@ request_params_C.pending_history_list_offset = 2; request_params_C.page_id = 3; request_params_C.page_state = state_C; - frame()->OnNavigate(common_params_C, StartNavigationParams(), - request_params_C); + NavigateFrame(common_params_C, StartNavigationParams(), request_params_C); ProcessPendingMessages(); render_thread_->sink().ClearMessages(); @@ -839,8 +850,7 @@ request_params_B.pending_history_list_offset = 1; request_params_B.page_id = 2; request_params_B.page_state = state_B; - frame()->OnNavigate(common_params_B, StartNavigationParams(), - request_params_B); + NavigateFrame(common_params_B, StartNavigationParams(), request_params_B); // Back to page A (page_id 1) and commit. CommonNavigationParams common_params; @@ -852,7 +862,7 @@ request_params.pending_history_list_offset = 0; request_params.page_id = 1; request_params.page_state = state_A; - frame()->OnNavigate(common_params, StartNavigationParams(), request_params); + NavigateFrame(common_params, StartNavigationParams(), request_params); ProcessPendingMessages(); // Now ensure that the UpdateState message we receive is consistent @@ -904,8 +914,7 @@ request_params_A.pending_history_list_offset = 0; request_params_A.page_id = 1; request_params_A.page_state = state_A; - frame()->OnNavigate(common_params_A, StartNavigationParams(), - request_params_A); + NavigateFrame(common_params_A, StartNavigationParams(), request_params_A); ProcessPendingMessages(); // A new navigation commits, clearing the forward history. @@ -925,8 +934,7 @@ request_params_B.page_id = 2; request_params_B.page_state = state_A; // Doesn't matter, just has to be present. - frame()->OnNavigate(common_params_B, StartNavigationParams(), - request_params_B); + NavigateFrame(common_params_B, StartNavigationParams(), request_params_B); // State should be unchanged. EXPECT_EQ(2, view()->history_list_length_); @@ -1641,8 +1649,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - frame()->OnNavigate(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -1664,8 +1672,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - frame()->OnNavigate(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // A cancellation occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -1862,8 +1870,8 @@ CommonNavigationParams common_params; common_params.url = GURL("data:text/html,min_zoomlimit_test"); view()->OnSetZoomLevelForLoadingURL(common_params.url, kMinZoomLevel); - frame()->OnNavigate(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); ProcessPendingMessages(); EXPECT_DOUBLE_EQ(kMinZoomLevel, view()->GetWebView()->zoomLevel()); @@ -1872,8 +1880,8 @@ ZoomFactorToZoomLevel(1.0)); common_params.url = GURL("data:text/html,max_zoomlimit_test"); view()->OnSetZoomLevelForLoadingURL(common_params.url, kMaxZoomLevel); - frame()->OnNavigate(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); ProcessPendingMessages(); EXPECT_DOUBLE_EQ(kMaxZoomLevel, view()->GetWebView()->zoomLevel()); } @@ -1945,7 +1953,7 @@ request_params.frame_to_navigate = "frame"; request_params.browser_navigation_start = base::TimeTicks::FromInternalValue(1); - frame()->OnNavigate(common_params, StartNavigationParams(), request_params); + NavigateFrame(common_params, StartNavigationParams(), request_params); FrameLoadWaiter( RenderFrame::FromWebFrame(frame()->GetWebFrame()->firstChild())).Wait(); @@ -2009,7 +2017,7 @@ EXPECT_LT(last_input_type, last_selection); } -class SuppressErrorPageTest : public RenderViewTest { +class SuppressErrorPageTest : public RenderViewImplTest { public: ContentRendererClient* CreateContentRendererClient() override { return new TestContentRendererClient; @@ -2062,8 +2070,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - frame()->OnNavigate(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -2092,8 +2100,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - frame()->OnNavigate(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -2303,8 +2311,7 @@ early_request_params.browser_navigation_start = base::TimeTicks::FromInternalValue(1); - frame()->OnNavigate(early_common_params, early_start_params, - early_request_params); + NavigateFrame(early_common_params, early_start_params, early_request_params); ProcessPendingMessages(); base::Time early_nav_reported_start = @@ -2324,8 +2331,7 @@ late_request_params.browser_navigation_start = base::TimeTicks::Now() + base::TimeDelta::FromDays(42); - frame()->OnNavigate(late_common_params, late_start_params, - late_request_params); + NavigateFrame(late_common_params, late_start_params, late_request_params); ProcessPendingMessages(); base::Time after_navigation = base::Time::Now() + base::TimeDelta::FromDays(1); @@ -2362,8 +2368,8 @@ request_params.current_history_list_offset = 1; request_params.pending_history_list_offset = 2; request_params.page_id = -1; - frame()->OnNavigate(CommonNavigationParams(), StartNavigationParams(), - request_params); + NavigateFrame(CommonNavigationParams(), StartNavigationParams(), + request_params); // The history list in RenderView should have been updated. EXPECT_EQ(1, view()->historyBackListCount());
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 4e6cb44..f524896b 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -147,7 +147,6 @@ #include "third_party/WebKit/public/web/WebHitTestResult.h" #include "third_party/WebKit/public/web/WebInputElement.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -#include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebMediaPlayerAction.h" #include "third_party/WebKit/public/web/WebNavigationPolicy.h" @@ -164,7 +163,6 @@ #include "third_party/WebKit/public/web/WebSearchableFormData.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" -#include "third_party/WebKit/public/web/WebSerializedScriptValue.h" #include "third_party/WebKit/public/web/WebSettings.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebView.h" @@ -224,8 +222,6 @@ using blink::WebData; using blink::WebDataSource; using blink::WebDocument; -using blink::WebDOMEvent; -using blink::WebDOMMessageEvent; using blink::WebDragData; using blink::WebDragOperation; using blink::WebDragOperationsMask; @@ -265,7 +261,6 @@ using blink::WebSearchableFormData; using blink::WebSecurityOrigin; using blink::WebSecurityPolicy; -using blink::WebSerializedScriptValue; using blink::WebSettings; using blink::WebSize; using blink::WebStorageNamespace; @@ -1280,7 +1275,6 @@ IPC_MESSAGE_HANDLER(ViewMsg_SetPageEncoding, OnSetPageEncoding) IPC_MESSAGE_HANDLER(ViewMsg_ResetPageEncodingToDefault, OnResetPageEncodingToDefault) - IPC_MESSAGE_HANDLER(ViewMsg_PostMessageEvent, OnPostMessageEvent) IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter) IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver) IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave) @@ -2530,61 +2524,6 @@ webview()->setPageEncoding(no_encoding); } -void RenderViewImpl::OnPostMessageEvent( - const ViewMsg_PostMessage_Params& params) { - // TODO(nasko): Support sending to subframes. - WebFrame* frame = webview()->mainFrame(); - - // Find the source frame if it exists. - WebFrame* source_frame = NULL; - if (params.source_routing_id != MSG_ROUTING_NONE) { - RenderViewImpl* source_view = FromRoutingID(params.source_routing_id); - if (source_view) - source_frame = source_view->webview()->mainFrame(); - } - - // If the message contained MessagePorts, create the corresponding endpoints. - blink::WebMessagePortChannelArray channels = - WebMessagePortChannelImpl::CreatePorts( - params.message_ports, params.new_routing_ids, - base::MessageLoopProxy::current().get()); - - WebSerializedScriptValue serialized_script_value; - if (params.is_data_raw_string) { - v8::HandleScope handle_scope(blink::mainThreadIsolate()); - v8::Local<v8::Context> context = frame->mainWorldScriptContext(); - v8::Context::Scope context_scope(context); - V8ValueConverterImpl converter; - converter.SetDateAllowed(true); - converter.SetRegExpAllowed(true); - scoped_ptr<base::Value> value(new base::StringValue(params.data)); - v8::Handle<v8::Value> result_value = converter.ToV8Value(value.get(), - context); - serialized_script_value = WebSerializedScriptValue::serialize(result_value); - } else { - serialized_script_value = WebSerializedScriptValue::fromString(params.data); - } - - // Create an event with the message. The final parameter to initMessageEvent - // is the last event ID, which is not used with postMessage. - WebDOMEvent event = frame->document().createEvent("MessageEvent"); - WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>(); - msg_event.initMessageEvent("message", - // |canBubble| and |cancellable| are always false - false, false, - serialized_script_value, - params.source_origin, source_frame, "", channels); - - // We must pass in the target_origin to do the security check on this side, - // since it may have changed since the original postMessage call was made. - WebSecurityOrigin target_origin; - if (!params.target_origin.empty()) { - target_origin = - WebSecurityOrigin::createFromString(WebString(params.target_origin)); - } - frame->dispatchMessageEventWithOriginCheck(target_origin, msg_event); -} - void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) { if ((enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) && !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 2b722ef..97b2606e 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -76,7 +76,6 @@ class SkBitmap; struct PP_NetAddress_Private; struct ViewMsg_New_Params; -struct ViewMsg_PostMessage_Params; struct ViewMsg_Resize_Params; struct ViewMsg_StopFinding_Params; @@ -652,7 +651,6 @@ void OnPluginActionAt(const gfx::Point& location, const blink::WebPluginAction& action); void OnMoveOrResizeStarted(); - void OnPostMessageEvent(const ViewMsg_PostMessage_Params& params); void OnReleaseDisambiguationPopupBitmap(const cc::SharedBitmapId& id); void OnResetPageEncodingToDefault(); void OnSetActive(bool active);
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc index ee1878c..e5199f1 100644 --- a/content/shell/app/shell_main_delegate.cc +++ b/content/shell/app/shell_main_delegate.cc
@@ -193,6 +193,8 @@ command_line.AppendSwitch(switches::kDisableDelegatedRenderer); command_line.AppendSwitch(cc::switches::kCompositeToMailbox); + command_line.AppendSwitch(cc::switches::kEnablePropertyTreeVerification); + command_line.AppendSwitch(switches::kEnablePreciseMemoryInfo); command_line.AppendSwitchASCII(switches::kHostResolverRules,
diff --git a/content/shell/common/shell_content_client.cc b/content/shell/common/shell_content_client.cc index 9f7ae1b..2e420895 100644 --- a/content/shell/common/shell_content_client.cc +++ b/content/shell/common/shell_content_client.cc
@@ -65,7 +65,7 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kRunLayoutTest)) { switch (resource_id) { - case IDR2_BROKENIMAGE: + case IDR_BROKENIMAGE: #if defined(OS_MACOSX) resource_id = IDR_CONTENT_SHELL_MISSING_IMAGE_PNG; #else @@ -73,7 +73,7 @@ #endif break; - case IDR2_TEXTAREA_RESIZER: + case IDR_TEXTAREA_RESIZER: resource_id = IDR_CONTENT_SHELL_TEXT_AREA_RESIZE_CORNER_PNG; break; }
diff --git a/content/shell/renderer/layout_test/webkit_test_runner.cc b/content/shell/renderer/layout_test/webkit_test_runner.cc index b33b290..19bb9310 100644 --- a/content/shell/renderer/layout_test/webkit_test_runner.cc +++ b/content/shell/renderer/layout_test/webkit_test_runner.cc
@@ -657,14 +657,17 @@ current_entry_indexes_.clear(); render_view()->ClearEditCommands(); - render_view()->GetWebView()->mainFrame()->setName(WebString()); + if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame()) + render_view()->GetWebView()->mainFrame()->setName(WebString()); render_view()->GetWebView()->mainFrame()->clearOpener(); // Resetting the internals object also overrides the WebPreferences, so we // have to sync them to WebKit again. - WebTestingSupport::resetInternalsObject( - render_view()->GetWebView()->mainFrame()->toWebLocalFrame()); - render_view()->SetWebkitPreferences(render_view()->GetWebkitPreferences()); + if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame()) { + WebTestingSupport::resetInternalsObject( + render_view()->GetWebView()->mainFrame()->toWebLocalFrame()); + render_view()->SetWebkitPreferences(render_view()->GetWebkitPreferences()); + } } // Private methods -----------------------------------------------------------
diff --git a/content/shell/renderer/test_runner/accessibility_controller.cc b/content/shell/renderer/test_runner/accessibility_controller.cc index 125f071..06531a0e 100644 --- a/content/shell/renderer/test_runner/accessibility_controller.cc +++ b/content/shell/renderer/test_runner/accessibility_controller.cc
@@ -168,7 +168,7 @@ v8::HandleScope handle_scope(isolate); blink::WebFrame* frame = web_view_->mainFrame(); - if (!frame) + if (!frame || frame->isWebRemoteFrame()) return; v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
diff --git a/content/shell/renderer/test_runner/web_ax_object_proxy.cc b/content/shell/renderer/test_runner/web_ax_object_proxy.cc index 1f29c4f..e37b8dad 100644 --- a/content/shell/renderer/test_runner/web_ax_object_proxy.cc +++ b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
@@ -226,8 +226,6 @@ return result.append("TableHeaderContainer"); case blink::WebAXRoleTable: return result.append("Table"); - case blink::WebAXRoleTextArea: - return result.append("TextArea"); case blink::WebAXRoleTextField: return result.append("TextField"); case blink::WebAXRoleTime:
diff --git a/content/test/data/frame_tree/page_with_post_message_frames.html b/content/test/data/frame_tree/page_with_post_message_frames.html new file mode 100644 index 0000000..6126299d --- /dev/null +++ b/content/test/data/frame_tree/page_with_post_message_frames.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<head><title>postMessage tests</title> +<script> + window.addEventListener("message", messageReceived, false); + + function messageReceived(event) { + document.title = event.data; + event.source.postMessage(event.data + "-reply", "*"); + } + +</script> +</head> +<body> + This page has two iframes that send postMessages: one is same-site, one is + cross-site. + <iframe name="subframe1" src="/post_message.html"></iframe> + <iframe name="subframe2" src="/cross-site/foo.com/post_message.html"></iframe> +</body> +</html> +
diff --git a/content/test/data/post_message.html b/content/test/data/post_message.html index 37adb83..e111fea 100644 --- a/content/test/data/post_message.html +++ b/content/test/data/post_message.html
@@ -15,6 +15,18 @@ return true; } + // Send a message to parent. + function postToParent(msg) { + parent.postMessage(msg, "*"); + return true; + } + + // Send a message to sibling. + function postToSibling(msg, sibling) { + parent.frames[sibling].postMessage(msg, "*"); + return true; + } + // Send a message to a subframe of window named "foo". function postToFooFrame(msg) { var w = window.open("", "foo"); @@ -30,6 +42,11 @@ receivedMessages++; if (event.data === "2-1-reply") { event.source.postMessage("msg4", "*"); + } else if (event.data === "subframe-msg") { + event.source.postMessage("subframe-msg-reply", "*"); + } else if (event.data === "subframe-msg-reply") { + domAutomationController.setAutomationId(0); + domAutomationController.send("done-" + window.name); } if (event.ports.length > 0) { receivedMessagesWithPort++;
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index e6351a6..3331a7a3 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -56,6 +56,10 @@ # Win / AMD failures self.Fail('conformance/textures/texparameter-test.html', ['win', 'amd', 'd3d9'], bug=839) # angle bug ID + self.Fail('conformance/extensions/angle-instanced-arrays.html', + ['win', 'amd', 'd3d9'], bug=475095) + self.Fail('conformance/rendering/more-than-65536-indices.html', + ['win', 'amd', 'd3d9'], bug=475095) # Win / D3D9 failures # Skipping these tests because they're causing assertion failures.
diff --git a/content/test/render_thread_impl_browser_test_ipc_helper.cc b/content/test/render_thread_impl_browser_test_ipc_helper.cc index 7f03885..e58f8c1 100644 --- a/content/test/render_thread_impl_browser_test_ipc_helper.cc +++ b/content/test/render_thread_impl_browser_test_ipc_helper.cc
@@ -54,6 +54,7 @@ channel_ = IPC::ChannelProxy::Create( IPC::ChannelMojo::CreateServerFactory(mojo_host_->channel_delegate(), + ipc_thread_->task_runner(), channel_id_), dummy_listener_.get(), ipc_thread_->task_runner());
diff --git a/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java b/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java index 8d62538..d833b2c9 100644 --- a/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java +++ b/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java
@@ -142,7 +142,7 @@ batteryStatus.dischargingTime = dischargingTimeSeconds; batteryStatus.level = level; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (mLollipopBatteryManager != null) { updateBatteryStatusForLollipop(batteryStatus); }
diff --git a/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java b/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java index 536e31b..2390d40 100644 --- a/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java +++ b/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java
@@ -35,6 +35,9 @@ private BatteryStatusManager mManager; + // Can be non-null only for versions L and higher. + private BatteryManagerForTesting mLollipopManager; + private void verifyValues( boolean charging, double chargingTime, double dischargingTime, double level) { assertEquals(charging, mCharging); @@ -85,6 +88,7 @@ } public void initializeManager(BatteryManagerForTesting managerForTesting) { + mLollipopManager = managerForTesting; mManager = BatteryStatusManager.createBatteryStatusManagerForTesting( getContext(), mCallback, managerForTesting); } @@ -168,11 +172,9 @@ @SmallTest public void testLollipopChargingTimeEstimate() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) - return; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; - BatteryManagerForTesting testManager = new BatteryManagerForTesting(); - initializeManager(testManager); + initializeManager(new BatteryManagerForTesting()); Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.putExtra(BatteryManager.EXTRA_PRESENT, true); @@ -180,9 +182,9 @@ intent.putExtra(BatteryManager.EXTRA_LEVEL, 50); intent.putExtra(BatteryManager.EXTRA_SCALE, 100); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1000); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 50); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, 100); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1000); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 50); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, 100); mManager.onReceive(intent); verifyValues(true, 0.5 * 10 * 3600, Double.POSITIVE_INFINITY, 0.5); @@ -190,11 +192,9 @@ @SmallTest public void testLollipopDischargingTimeEstimate() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) - return; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; - BatteryManagerForTesting testManager = new BatteryManagerForTesting(); - initializeManager(testManager); + initializeManager(new BatteryManagerForTesting()); Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.putExtra(BatteryManager.EXTRA_PRESENT, true); @@ -203,9 +203,9 @@ intent.putExtra(BatteryManager.EXTRA_SCALE, 100); intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_NOT_CHARGING); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1000); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 60); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, -100); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1000); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 60); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, -100); mManager.onReceive(intent); verifyValues(false, Double.POSITIVE_INFINITY, 0.6 * 10 * 3600, 0.6); @@ -213,11 +213,9 @@ @SmallTest public void testLollipopDischargingTimeEstimateRounding() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) - return; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; - BatteryManagerForTesting testManager = new BatteryManagerForTesting(); - initializeManager(testManager); + initializeManager(new BatteryManagerForTesting()); Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); intent.putExtra(BatteryManager.EXTRA_PRESENT, true); @@ -226,9 +224,9 @@ intent.putExtra(BatteryManager.EXTRA_SCALE, 100); intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_NOT_CHARGING); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1999); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 90); - testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, -1000); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1999); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 90); + mLollipopManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, -1000); mManager.onReceive(intent); verifyValues(false, Double.POSITIVE_INFINITY, Math.floor(0.9 * 1.999 * 3600), 0.9);
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 34c4a15..d0790d87 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -422,14 +422,14 @@ // WebContents::GetRenderWidgetHostView will return the RWHV of an // interstitial page if one is showing at this time. We only want opacity // to apply to web pages. - if (guest_opaque_) { + if (allow_transparency_) { + web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor( + SK_ColorTRANSPARENT); + } else { web_contents() ->GetRenderViewHost() ->GetView() ->SetBackgroundColorToDefault(); - } else { - web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor( - SK_ColorTRANSPARENT); } } @@ -721,7 +721,7 @@ rules_registry_id_(RulesRegistryService::kInvalidRulesRegistryID), find_helper_(this), is_overriding_user_agent_(false), - guest_opaque_(true), + allow_transparency_(false), javascript_dialog_helper_(this), allow_scaling_(false), is_guest_fullscreen_(false), @@ -1018,14 +1018,16 @@ SetUserAgentOverride(user_agent_override); bool allow_transparency = false; - params.GetBoolean(webview::kAttributeAllowTransparency, &allow_transparency); - // We need to set the background opaque flag after navigation to ensure that - // there is a RenderWidgetHostView available. - SetAllowTransparency(allow_transparency); + if (params.GetBoolean(webview::kAttributeAllowTransparency, + &allow_transparency)) { + // We need to set the background opaque flag after navigation to ensure that + // there is a RenderWidgetHostView available. + SetAllowTransparency(allow_transparency); + } bool allow_scaling = false; - params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling); - SetAllowScaling(allow_scaling); + if (params.GetBoolean(webview::kAttributeAllowScaling, &allow_scaling)) + SetAllowScaling(allow_scaling); bool is_pending_new_window = false; if (GetOpener()) { @@ -1082,21 +1084,21 @@ } void WebViewGuest::SetAllowTransparency(bool allow) { - if (guest_opaque_ != allow) + if (allow_transparency_ == allow) return; - guest_opaque_ = !allow; + allow_transparency_ = allow; if (!web_contents()->GetRenderViewHost()->GetView()) return; - if (guest_opaque_) { + if (allow_transparency_) { + web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor( + SK_ColorTRANSPARENT); + } else { web_contents() ->GetRenderViewHost() ->GetView() ->SetBackgroundColorToDefault(); - } else { - web_contents()->GetRenderViewHost()->GetView()->SetBackgroundColor( - SK_ColorTRANSPARENT); } }
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index d6f3e329..34f5df95 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -89,9 +89,11 @@ void SetZoomMode(ui_zoom::ZoomController::ZoomMode zoom_mode); void SetAllowScaling(bool allow); + bool allow_scaling() const { return allow_scaling_; } // Sets the transparency of the guest. void SetAllowTransparency(bool allow); + bool allow_transparency() const { return allow_transparency_; } // Loads a data URL with a specified base URL and virtual URL. bool LoadDataWithBaseURL(const std::string& data_url, @@ -364,7 +366,7 @@ std::string name_; // Stores whether the contents of the guest can be transparent. - bool guest_opaque_; + bool allow_transparency_; // Stores the src URL of the WebView. GURL src_;
diff --git a/extensions/extensions_strings.grd b/extensions/extensions_strings.grd index 4dce699..fec2b34 100644 --- a/extensions/extensions_strings.grd +++ b/extensions/extensions_strings.grd
@@ -321,20 +321,20 @@ <message name="IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE" desc="Permission string for network list access."> Access list of network connections </message> - <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST" desc="Permission string for access to any computer on the local network or internet."> - Exchange data with any computer on the local network or internet + <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST" desc="Permission string for access to any device on the local network or internet."> + Exchange data with any device on the local network or internet </message> - <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN" desc="Permission string for access to any computer within a single domains on the local network or internet."> - Exchange data with any computer in the domain <ph name="DOMAIN">$1<ex>example.com</ex></ph> + <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN" desc="Permission string for access to any device within a single domains on the local network or internet."> + Exchange data with any device in the domain <ph name="DOMAIN">$1<ex>example.com</ex></ph> </message> - <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS" desc="Permission string for access to any computer within multiple domains on the local network or internet."> - Exchange data with any computer in the domains: <ph name="DOMAINS">$1<ex>example.com example.org</ex></ph> + <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS" desc="Permission string for access to any device within multiple domains on the local network or internet."> + Exchange data with any device in the domains: <ph name="DOMAINS">$1<ex>example.com example.org</ex></ph> </message> - <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST" desc="Permission string for access to a single specific computers on the local network or internet."> - Exchange data with the computer named <ph name="HOSTNAME">$1<ex>foo.example.com</ex></ph> + <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST" desc="Permission string for access to a single specific device on the local network or internet."> + Exchange data with the device named <ph name="HOSTNAME">$1<ex>foo.example.com</ex></ph> </message> - <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS" desc="Permission string for access to multiple specific computers on the local network or internet."> - Exchange data with the computers named: <ph name="HOSTNAMES">$1<ex>foo.example.com bar.example.com</ex></ph> + <message name="IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS" desc="Permission string for access to multiple specific devices on the local network or internet."> + Exchange data with the devices named: <ph name="HOSTNAMES">$1<ex>foo.example.com bar.example.com</ex></ph> </message> <!-- Device API strings. Please keep alphabetized. -->
diff --git a/extensions/shell/browser/shell_desktop_controller_aura.cc b/extensions/shell/browser/shell_desktop_controller_aura.cc index 1f45df2..ffa1383 100644 --- a/extensions/shell/browser/shell_desktop_controller_aura.cc +++ b/extensions/shell/browser/shell_desktop_controller_aura.cc
@@ -279,8 +279,6 @@ aura::client::SetCursorClient(host_->window(), cursor_manager_.get()); user_activity_detector_.reset(new ui::UserActivityDetector); - host_->event_processor()->GetRootTarget()->AddPreTargetHandler( - user_activity_detector_.get()); #if defined(OS_CHROMEOS) user_activity_notifier_.reset( new ui::UserActivityPowerManagerNotifier(user_activity_detector_.get())); @@ -324,10 +322,6 @@ host_->RemoveObserver(this); if (input_method_filter_) root_window_event_filter_->RemoveHandler(input_method_filter_.get()); - if (user_activity_detector_) { - host_->event_processor()->GetRootTarget()->RemovePreTargetHandler( - user_activity_detector_.get()); - } wm::FocusController* focus_controller = static_cast<wm::FocusController*>(focus_client_.get()); if (focus_controller) {
diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc index 5622460..bf2331d9 100644 --- a/google_apis/gaia/fake_gaia.cc +++ b/google_apis/gaia/fake_gaia.cc
@@ -56,6 +56,9 @@ const base::FilePath::CharType kServiceLogin[] = FILE_PATH_LITERAL("google_apis/test/service_login.html"); +const base::FilePath::CharType kEmbeddedSetupChromeos[] = + FILE_PATH_LITERAL("google_apis/test/embedded_setup_chromeos.html"); + // OAuth2 Authentication header value prefix. const char kAuthHeaderBearer[] = "Bearer "; const char kAuthHeaderOAuth[] = "OAuth "; @@ -139,6 +142,9 @@ CHECK(base::ReadFileToString( source_root_dir.Append(base::FilePath(kServiceLogin)), &service_login_response_)); + CHECK(base::ReadFileToString( + source_root_dir.Append(base::FilePath(kEmbeddedSetupChromeos)), + &embedded_setup_chromeos_response_)); } FakeGaia::~FakeGaia() {} @@ -213,9 +219,8 @@ gaia_urls->service_login_url(), HandleServiceLogin); // Handles /embedded/setup/chromeos GAIA call. - // Same handler as for /ServiceLogin is used for now. - REGISTER_RESPONSE_HANDLER( - gaia_urls->embedded_setup_chromeos_url(), HandleServiceLogin); + REGISTER_RESPONSE_HANDLER(gaia_urls->embedded_setup_chromeos_url(), + HandleEmbeddedSetupChromeos); // Handles /OAuthLogin GAIA call. REGISTER_RESPONSE_HANDLER( @@ -225,6 +230,16 @@ REGISTER_RESPONSE_HANDLER( gaia_urls->service_login_auth_url(), HandleServiceLoginAuth); + // Handles /_/embedded/lookup/accountlookup for /embedded/setup/chromeos + // authentication request. + REGISTER_PATH_RESPONSE_HANDLER("/_/embedded/lookup/accountlookup", + HandleEmbeddedLookupAccountLookup); + + // Handles /_/embedded/signin/challenge for /embedded/setup/chromeos + // authentication request. + REGISTER_PATH_RESPONSE_HANDLER("/_/embedded/signin/challenge", + HandleEmbeddedSigninChallenge); + // Handles /SSO GAIA call (not GAIA, made up for SAML tests). REGISTER_PATH_RESPONSE_HANDLER("/SSO", HandleSSO); @@ -424,6 +439,13 @@ http_response->set_content_type("text/html"); } +void FakeGaia::HandleEmbeddedSetupChromeos(const HttpRequest& request, + BasicHttpResponse* http_response) { + http_response->set_code(net::HTTP_OK); + http_response->set_content(embedded_setup_chromeos_response_); + http_response->set_content_type("text/html"); +} + void FakeGaia::HandleOAuthLogin(const HttpRequest& request, BasicHttpResponse* http_response) { http_response->set_code(net::HTTP_UNAUTHORIZED); @@ -501,6 +523,45 @@ SetOAuthCodeCookie(http_response); } +void FakeGaia::HandleEmbeddedLookupAccountLookup( + const net::test_server::HttpRequest& request, + net::test_server::BasicHttpResponse* http_response) { + std::string email; + const bool is_saml = + GetQueryParameter(request.content, "identifier", &email) && + saml_account_idp_map_.find(email) != saml_account_idp_map_.end(); + + if (!is_saml) + return; + + GURL url(saml_account_idp_map_[email]); + url = net::AppendQueryParameter(url, "SAMLRequest", "fake_request"); + url = net::AppendQueryParameter( + url, "RelayState", + "chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/success.html"); + std::string redirect_url = url.spec(); + http_response->AddCustomHeader("Google-Accounts-SAML", "Start"); + + http_response->AddCustomHeader("continue", redirect_url); +} + +void FakeGaia::HandleEmbeddedSigninChallenge(const HttpRequest& request, + BasicHttpResponse* http_response) { + std::string email; + GetQueryParameter(request.content, "identifier", &email); + + if (!merge_session_params_.auth_sid_cookie.empty() && + !merge_session_params_.auth_lsid_cookie.empty()) { + SetCookies(http_response, merge_session_params_.auth_sid_cookie, + merge_session_params_.auth_lsid_cookie); + } + + AddGoogleAccountsSigninHeader(http_response, email); + + if (issue_oauth_code_cookie_) + SetOAuthCodeCookie(http_response); +} + void FakeGaia::HandleSSO(const HttpRequest& request, BasicHttpResponse* http_response) { if (!merge_session_params_.auth_sid_cookie.empty() &&
diff --git a/google_apis/gaia/fake_gaia.h b/google_apis/gaia/fake_gaia.h index b66c02f..e50b7cb 100644 --- a/google_apis/gaia/fake_gaia.h +++ b/google_apis/gaia/fake_gaia.h
@@ -158,11 +158,20 @@ net::test_server::BasicHttpResponse* http_response); void HandleServiceLogin(const net::test_server::HttpRequest& request, net::test_server::BasicHttpResponse* http_response); + void HandleEmbeddedSetupChromeos( + const net::test_server::HttpRequest& request, + net::test_server::BasicHttpResponse* http_response); void HandleOAuthLogin(const net::test_server::HttpRequest& request, net::test_server::BasicHttpResponse* http_response); void HandleServiceLoginAuth( const net::test_server::HttpRequest& request, net::test_server::BasicHttpResponse* http_response); + void HandleEmbeddedLookupAccountLookup( + const net::test_server::HttpRequest& request, + net::test_server::BasicHttpResponse* http_response); + void HandleEmbeddedSigninChallenge( + const net::test_server::HttpRequest& request, + net::test_server::BasicHttpResponse* http_response); void HandleSSO(const net::test_server::HttpRequest& request, net::test_server::BasicHttpResponse* http_response); void HandleAuthToken(const net::test_server::HttpRequest& request, @@ -198,6 +207,7 @@ AccessTokenInfoMap access_token_info_map_; RequestHandlerMap request_handlers_; std::string service_login_response_; + std::string embedded_setup_chromeos_response_; SamlAccountIdpMap saml_account_idp_map_; bool issue_oauth_code_cookie_;
diff --git a/google_apis/test/embedded_setup_chromeos.html b/google_apis/test/embedded_setup_chromeos.html new file mode 100644 index 0000000..d2175f0 --- /dev/null +++ b/google_apis/test/embedded_setup_chromeos.html
@@ -0,0 +1,110 @@ +<html> +<head> +<script> +var gaia = gaia || {}; +gaia.chromeOSLogin = {}; + +gaia.chromeOSLogin.parent_webview_signin_url_ = 'chrome://chrome-signin'; +gaia.chromeOSLogin.parent_webview_oob_url_ = 'chrome://oobe'; +gaia.chromeOSLogin.parent_webview_ = undefined; +gaia.chromeOSLogin.parent_webview_url_ = undefined; + +gaia.chromeOSLogin.registerHtml5Listener = function() { + var onMessage = function(e) { + if (e.origin == gaia.chromeOSLogin.parent_webview_signin_url_ || + e.origin == gaia.chromeOSLogin.parent_webview_oob_url_) { + gaia.chromeOSLogin.parent_webview_ = e.source; + gaia.chromeOSLogin.parent_webview_url_ = e.origin; + + // Repeat clearOldAttempts as soon as we got parent. + gaia.chromeOSLogin.clearOldAttempts(); + } + }; + window.addEventListener('message', onMessage); +} + +gaia.chromeOSLogin.clearOldAttempts = function() { + var msg = { + 'method': 'clearOldAttempts' + }; + gaia.chromeOSLogin.parent_webview_.postMessage(msg, + gaia.chromeOSLogin.parent_webview_url_); +}; + +gaia.chromeOSLogin.attemptLogin = function(email, password) { + var msg = { + 'method': 'attemptLogin', + 'email': email, + 'password': password, + }; + gaia.chromeOSLogin.parent_webview_.postMessage(msg, + gaia.chromeOSLogin.parent_webview_url_); +}; + +gaia.chromeOSLogin.backButton = function(show) { + var msg = { + 'method': 'backButton', + 'show': show, + }; + gaia.chromeOSLogin.parent_webview_.postMessage(msg, + gaia.chromeOSLogin.parent_webview_url_); +}; + +function goNext() { + if (!document.getElementById("page1").hidden) { + document.getElementById("page1").hidden = true; + document.getElementById("page2").hidden = false; + history.pushState({}, "", window.location.pathname + "#challengepassword"); + + request = new XMLHttpRequest(); + request.open('POST', '/_/embedded/lookup/accountlookup', true); + request.onreadystatechange = function() { + if (request.readyState == 4 && request.status == 200) { + if (request.getResponseHeader("continue")) + location.assign(request.getResponseHeader("continue")); + } + }; + var email = document.getElementById("identifier").value; + request.send('identifier=' + encodeURIComponent(email)); + + gaia.chromeOSLogin.attemptLogin(email, ""); + gaia.chromeOSLogin.backButton(true); + } else if (!document.getElementById("page2").hidden) { + var email = document.getElementById("identifier").value; + var password = document.getElementById("password").value; + + request = new XMLHttpRequest(); + request.open('POST', '/_/embedded/signin/challenge', true); + request.onreadystatechange = function() { + if (request.readyState == 4 && request.status == 200) { + history.pushState({}, "", window.location.pathname + "#close"); + } + }; + request.send('identifier=' + encodeURIComponent(email)); + + gaia.chromeOSLogin.attemptLogin(email, password); + } +} + +function onLoad() { + gaia.chromeOSLogin.registerHtml5Listener(); + document.getElementById("page1").hidden = false; + history.replaceState({}, "", window.location.pathname + "#identifier"); + gaia.chromeOSLogin.clearOldAttempts(); +} + +</script> +</head> +<body onload='onLoad();'> + Local Auth Server:<br> + <div id="page1" hidden> + Email + <input id="identifier" name="identifier" type="email" spellcheck="false" autocomplete="off" formnovalidate=""> + </div> + <div id="page2" hidden> + Password + <input id="password" name="password" type="password" spellcheck="false" autocomplete="off" formnovalidate=""> + </div><br> + <div id='nextButton' onclick='goNext();'>Next</div> +</body> +</html>
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt index 645a3f4..e0ba066 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_image.txt
@@ -15,6 +15,7 @@ OpenGL ES 2.0 is required. EXT_texture_format_BGRA8888 affects the definition of this extension. + ARB_texture_rg affects the definition of this extension. Overview @@ -45,7 +46,7 @@ INVALID_VALUE is generated if <width> or <height> is nonpositive. INVALID_ENUM is generated if <internalformat> is not one of - RGB, RGBA or GL_BGRA_EXT. + R8, RGB, RGBA or BGRA_EXT. void DestroyImageCHROMIUM(GLuint image_id) @@ -56,7 +57,12 @@ Dependencies on EXT_texture_format_BGRA8888 If EXT_texture_format_BGRA8888 is not supported: - * delete any reference to the GL_BGRA_EXT format. + * delete any reference to the BGRA_EXT format. + +Dependencies on ARB_texture_rg + + If ARB_texture_rg is not supported: + * delete any reference to the R8 format. Errors @@ -71,4 +77,5 @@ 5/9/2013 Documented the extension 4/30/2014 Moved usage flag to creation function. 10/7/2014 Remove map/unmap API. - 4/6/2015 Add GL_BGRA_EXT format. + 4/6/2015 Add BGRA_EXT format. + 2/7/2015 Add R8 format.
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index c93017c..1327826e 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -4829,6 +4829,7 @@ bool ValidImageFormat(GLenum internalformat) { switch (internalformat) { + case GL_R8: case GL_RGB: case GL_RGBA: case GL_BGRA_EXT:
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index dcbdb8f..84fc2e4 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -1070,7 +1070,9 @@ validators_.texture_format.AddValue(GL_RED_EXT); validators_.texture_format.AddValue(GL_RG_EXT); validators_.texture_internal_format.AddValue(GL_RED_EXT); + validators_.texture_internal_format.AddValue(GL_R8_EXT); validators_.texture_internal_format.AddValue(GL_RG_EXT); + validators_.texture_internal_format.AddValue(GL_RG8_EXT); validators_.read_pixel_format.AddValue(GL_RED_EXT); validators_.read_pixel_format.AddValue(GL_RG_EXT); validators_.render_buffer_format.AddValue(GL_R8_EXT); @@ -1088,6 +1090,7 @@ texture_format_validators_[GL_RG_EXT].AddValue(GL_HALF_FLOAT_OES); } } + UMA_HISTOGRAM_BOOLEAN("GPU.TextureRG", feature_flags_.ext_texture_rg); #if !defined(OS_MACOSX) if (workarounds_.ignore_egl_sync_failures) {
diff --git a/gpu/command_buffer/service/image_factory.cc b/gpu/command_buffer/service/image_factory.cc index f09cfb8..74994ff 100644 --- a/gpu/command_buffer/service/image_factory.cc +++ b/gpu/command_buffer/service/image_factory.cc
@@ -19,6 +19,8 @@ gfx::GpuMemoryBuffer::Format ImageFactory::ImageFormatToGpuMemoryBufferFormat( unsigned internalformat) { switch (internalformat) { + case GL_R8: + return gfx::GpuMemoryBuffer::R_8; case GL_RGB: return gfx::GpuMemoryBuffer::RGBX_8888; case GL_RGBA: @@ -78,6 +80,8 @@ return capabilities.texture_format_dxt5; case gfx::GpuMemoryBuffer::ETC1: return capabilities.texture_format_etc1; + case gfx::GpuMemoryBuffer::R_8: + return capabilities.texture_rg; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::YUV_420: @@ -101,6 +105,7 @@ // Compressed images must have a width and height that's evenly divisible // by the block size. return size.width() % 4 == 0 && size.height() % 4 == 0; + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: case gfx::GpuMemoryBuffer::RGBX_8888:
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index 65986f82..71a6532 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -713,6 +713,8 @@ int32 new_id = next_image_id_.GetNext(); + DCHECK(gpu::ImageFactory::IsGpuMemoryBufferFormatSupported( + gpu_memory_buffer->GetFormat(), capabilities_)); DCHECK(gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat( internalformat, gpu_memory_buffer->GetFormat()));
diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc index 9368da5..51b3640 100644 --- a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc +++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
@@ -80,6 +80,9 @@ std::vector<uint8> GetTexturePixel(const gfx::GpuMemoryBuffer::Format format) { std::vector<uint8> pixel; switch (format) { + case gfx::GpuMemoryBuffer::R_8: + pixel.push_back(255u); + return pixel; case gfx::GpuMemoryBuffer::RGBA_8888: pixel.push_back(255u); pixel.push_back(0u); @@ -111,6 +114,7 @@ const gfx::GpuMemoryBuffer::Format format) { std::vector<uint8> pixel; switch (format) { + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: pixel.push_back(255u); @@ -135,6 +139,8 @@ GLenum InternalFormat(gfx::GpuMemoryBuffer::Format format) { switch (format) { + case gfx::GpuMemoryBuffer::R_8: + return GL_R8; case gfx::GpuMemoryBuffer::RGBA_8888: return GL_RGBA; case gfx::GpuMemoryBuffer::BGRA_8888: @@ -158,6 +164,9 @@ // An end to end test that tests the whole GpuMemoryBuffer lifecycle. TEST_P(GpuMemoryBufferTest, Lifecycle) { + ASSERT_TRUE((GetParam() != gfx::GpuMemoryBuffer::R_8) || + gl_.GetCapabilities().texture_rg); + GLuint texture_id = 0; glGenTextures(1, &texture_id); ASSERT_NE(0u, texture_id); @@ -243,7 +252,8 @@ INSTANTIATE_TEST_CASE_P(GpuMemoryBufferTests, GpuMemoryBufferTest, - ::testing::Values(gfx::GpuMemoryBuffer::RGBA_8888, + ::testing::Values(gfx::GpuMemoryBuffer::R_8, + gfx::GpuMemoryBuffer::RGBA_8888, gfx::GpuMemoryBuffer::BGRA_8888)); } // namespace gles2
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 3a3d7e9..2b6d06d 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -46,6 +46,7 @@ case gfx::GpuMemoryBuffer::Format::DXT1: case gfx::GpuMemoryBuffer::Format::DXT5: case gfx::GpuMemoryBuffer::Format::ETC1: + case gfx::GpuMemoryBuffer::Format::R_8: case gfx::GpuMemoryBuffer::Format::RGBA_8888: case gfx::GpuMemoryBuffer::Format::RGBX_8888: case gfx::GpuMemoryBuffer::Format::BGRA_8888: @@ -64,6 +65,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::BGRA_8888: @@ -92,6 +94,8 @@ DCHECK_EQ(plane, 0); DCHECK_EQ(width % 2, 0U); return width / 2; + case gfx::GpuMemoryBuffer::R_8: + return (width + 3) & ~0x3; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: DCHECK_EQ(plane, 0);
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc index 2cba5d8..3653a10 100644 --- a/gpu/config/gpu_info.cc +++ b/gpu/config/gpu_info.cc
@@ -79,6 +79,7 @@ std::string driver_date; std::string pixel_shader_version; std::string vertex_shader_version; + std::string max_msaa_samples; std::string machine_model_name; std::string machine_model_version; std::string gl_version_string; @@ -135,6 +136,7 @@ enumerator->AddString("driverDate", driver_date); enumerator->AddString("pixelShaderVersion", pixel_shader_version); enumerator->AddString("vertexShaderVersion", vertex_shader_version); + enumerator->AddString("maxMsaaSamples", max_msaa_samples); enumerator->AddString("glVersion", gl_version); enumerator->AddString("glVendor", gl_vendor); enumerator->AddString("glRenderer", gl_renderer);
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h index e5bef23..cbd8361 100644 --- a/gpu/config/gpu_info.h +++ b/gpu/config/gpu_info.h
@@ -138,6 +138,10 @@ // The version of the vertex shader used by the gpu. std::string vertex_shader_version; + // The maximum multisapling sample count, either through ES3 or + // EXT_multisampled_render_to_texture MSAA. + std::string max_msaa_samples; + // The machine model identifier. They can contain any character, including // whitespaces. Currently it is supported on MacOSX and Android. // Android examples: "Naxus 5", "XT1032".
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc index 521f2cd..c673057 100644 --- a/gpu/config/gpu_info_collector.cc +++ b/gpu/config/gpu_info_collector.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" +#include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" @@ -101,6 +102,9 @@ gpu_info->gl_extensions = GetGLString(GL_EXTENSIONS); gpu_info->gl_version = GetGLString(GL_VERSION); std::string glsl_version_string = GetGLString(GL_SHADING_LANGUAGE_VERSION); + GLint max_samples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + gpu_info->max_msaa_samples = base::StringPrintf("%d", max_samples); gfx::GLWindowSystemBindingInfo window_system_binding_info; if (GetGLWindowSystemBindingInfo(&window_system_binding_info)) { @@ -141,6 +145,8 @@ context_gpu_info.pixel_shader_version; basic_gpu_info->vertex_shader_version = context_gpu_info.vertex_shader_version; + basic_gpu_info->max_msaa_samples = + context_gpu_info.max_msaa_samples; basic_gpu_info->gl_ws_vendor = context_gpu_info.gl_ws_vendor; basic_gpu_info->gl_ws_version = context_gpu_info.gl_ws_version; basic_gpu_info->gl_ws_extensions = context_gpu_info.gl_ws_extensions;
diff --git a/gpu/config/gpu_info_unittest.cc b/gpu/config/gpu_info_unittest.cc index 71d4e5c..1d5fa6ee 100644 --- a/gpu/config/gpu_info_unittest.cc +++ b/gpu/config/gpu_info_unittest.cc
@@ -19,6 +19,7 @@ EXPECT_EQ(gpu_info.driver_date, ""); EXPECT_EQ(gpu_info.pixel_shader_version, ""); EXPECT_EQ(gpu_info.vertex_shader_version, ""); + EXPECT_EQ(gpu_info.max_msaa_samples, ""); EXPECT_EQ(gpu_info.gl_version, ""); EXPECT_EQ(gpu_info.gl_vendor, ""); EXPECT_EQ(gpu_info.gl_renderer, "");
diff --git a/ios/chrome/browser/memory/OWNERS b/ios/chrome/browser/memory/OWNERS new file mode 100644 index 0000000..f723afb --- /dev/null +++ b/ios/chrome/browser/memory/OWNERS
@@ -0,0 +1 @@ +lliabraa@chromium.org
diff --git a/ios/chrome/browser/memory/memory_debugger.h b/ios/chrome/browser/memory/memory_debugger.h new file mode 100644 index 0000000..a3c9c07 --- /dev/null +++ b/ios/chrome/browser/memory/memory_debugger.h
@@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_MEMORY_MEMORY_DEBUGGER_H_ +#define IOS_CHROME_BROWSER_MEMORY_MEMORY_DEBUGGER_H_ + +#import <UIKit/UIKit.h> + +// A view that contains memory information (e.g. amount of free memory) and +// tools (e.g. trigger memory warning) to help investigate memory issues and +// performance. +// +// The debugger ensures that it remains visible by continuously calling +// bringSubviewToFront on it's parent so it should be added as a subview of the +// the application's window in order to stay visible all the times. +// +// The debugger owns some timers that must be invalidated before it can be +// deallocated so the owner must call |invalidateTimers| before a MemoryDebugger +// instance can be deallocated. +@interface MemoryDebugger : UIView<UITextFieldDelegate> +// Must be called before the object can be deallocated! +- (void)invalidateTimers; +@end + +#endif // IOS_CHROME_BROWSER_MEMORY_MEMORY_DEBUGGER_H_
diff --git a/ios/chrome/browser/memory/memory_debugger.mm b/ios/chrome/browser/memory/memory_debugger.mm new file mode 100644 index 0000000..22bf881 --- /dev/null +++ b/ios/chrome/browser/memory/memory_debugger.mm
@@ -0,0 +1,600 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/memory/memory_debugger.h" + +#include "base/ios/ios_util.h" +#import "base/mac/scoped_nsobject.h" +#import "base/memory/scoped_ptr.h" +#import "ios/chrome/browser/memory/memory_metrics.h" +#include "ios/chrome/browser/ui/ui_util.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" + +namespace { +// The number of bytes in a megabyte. +const CGFloat kNumBytesInMB = 1024 * 1024; +// The horizontal and vertical padding between subviews. +const CGFloat kPadding = 10; +} // namespace + +@implementation MemoryDebugger { + // A timer to trigger refreshes. + base::scoped_nsobject<NSTimer> _refreshTimer; + + // A timer to trigger continuous memory warnings. + base::scoped_nsobject<NSTimer> _memoryWarningTimer; + + // The font to use. + base::scoped_nsobject<UIFont> _font; + + // Labels for memory metrics. + base::scoped_nsobject<UILabel> _physicalFreeMemoryLabel; + base::scoped_nsobject<UILabel> _realMemoryUsedLabel; + base::scoped_nsobject<UILabel> _xcodeGaugeLabel; + base::scoped_nsobject<UILabel> _dirtyVirtualMemoryLabel; + + // Inputs for memory commands. + base::scoped_nsobject<UITextField> _bloatField; + base::scoped_nsobject<UITextField> _refreshField; + base::scoped_nsobject<UITextField> _continuousMemoryWarningField; + + // A place to store the artifical memory bloat. + scoped_ptr<uint8> _bloat; + + // Distance the view was pushed up to accomodate the keyboard. + CGFloat _keyboardOffset; + + // The current orientation of the device. + BOOL _currentOrientation; +} + +- (instancetype)init { + self = [super initWithFrame:CGRectZero]; + if (self) { + _font.reset([[UIFont systemFontOfSize:14] retain]); + self.backgroundColor = [UIColor colorWithWhite:0.8f alpha:0.9f]; + self.opaque = NO; + + [self addSubviews]; + [self adjustForOrientation:nil]; + [self sizeToFit]; + [self registerForNotifications]; + } + return self; +} + +// NSTimers create a retain cycle so they must be invalidated before this +// instance can be deallocated. +- (void)invalidateTimers { + [_refreshTimer invalidate]; + [_memoryWarningTimer invalidate]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +#pragma mark UIView methods + +- (CGSize)sizeThatFits:(CGSize)size { + CGFloat width = 0; + CGFloat height = 0; + for (UIView* subview in self.subviews) { + width = MAX(width, CGRectGetMaxX(subview.frame)); + height = MAX(height, CGRectGetMaxY(subview.frame)); + } + return CGSizeMake(width + kPadding, height + kPadding); +} + +#pragma mark initialization helpers + +- (void)addSubviews { + // |index| is used to calculate the vertical position of each element in + // the debugger view. + NSUInteger index = 0; + + // Display some metrics. + _physicalFreeMemoryLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]); + [self addMetricWithName:@"Physical Free" + atIndex:index++ + usingLabel:_physicalFreeMemoryLabel]; + _realMemoryUsedLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]); + [self addMetricWithName:@"Real Memory Used" + atIndex:index++ + usingLabel:_realMemoryUsedLabel]; + _xcodeGaugeLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]); + [self addMetricWithName:@"Xcode Gauge" + atIndex:index++ + usingLabel:_xcodeGaugeLabel]; + _dirtyVirtualMemoryLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]); + [self addMetricWithName:@"Dirty VM" + atIndex:index++ + usingLabel:_dirtyVirtualMemoryLabel]; + +// Since _performMemoryWarning is a private API it can't be compiled into +// official builds. +// TODO(lliabraa): Figure out how to support memory warnings (or something +// like them) in official builds. +#if CHROMIUM_BUILD + [self addButtonWithTitle:@"Trigger Memory Warning" + target:[UIApplication sharedApplication] + action:@selector(_performMemoryWarning) + withOrigin:[self originForSubviewAtIndex:index++]]; +#endif // CHROMIUM_BUILD + + // Display a text input to set the amount of artificial memory bloat and a + // button to reset the bloat to zero. + _bloatField.reset([[UITextField alloc] initWithFrame:CGRectZero]); + [self addLabelWithText:@"Set bloat (MB)" + input:_bloatField + inputTarget:self + inputAction:@selector(updateBloat) + buttonWithTitle:@"Clear" + buttonTarget:self + buttonAction:@selector(clearBloat) + atIndex:index++]; + [_bloatField setText:@"0"]; + [self updateBloat]; + +// Since _performMemoryWarning is a private API it can't be compiled into +// official builds. +// TODO(lliabraa): Figure out how to support memory warnings (or something +// like them) in official builds. +#if CHROMIUM_BUILD + // Display a text input to control the rate of continuous memory warnings. + _continuousMemoryWarningField.reset( + [[UITextField alloc] initWithFrame:CGRectZero]); + [self addLabelWithText:@"Set memory warning interval (secs)" + input:_continuousMemoryWarningField + inputTarget:self + inputAction:@selector(updateMemoryWarningInterval) + atIndex:index++]; + [_continuousMemoryWarningField setText:@"0.0"]; +#endif // CHROMIUM_BUILD + + // Display a text input to control the refresh rate of the memory debugger. + _refreshField.reset([[UITextField alloc] initWithFrame:CGRectZero]); + [self addLabelWithText:@"Set refresh interval (secs)" + input:_refreshField + inputTarget:self + inputAction:@selector(updateRefreshInterval) + atIndex:index++]; + [_refreshField setText:@"0.5"]; + [self updateRefreshInterval]; +} + +- (void)registerForNotifications { + // On iOS 7, the screen coordinate system is not dependent on orientation so + // the debugger has to handle its own rotation. + if (!base::ios::IsRunningOnIOS8OrLater()) { + // Register to receive orientation notifications. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(adjustForOrientation:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; + } + + // Register to receive memory warning. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(lowMemoryWarningReceived:) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; + + // Register to receive keyboard will show notification. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:nil]; + + // Register to receive keyboard will hide notification. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:nil]; +} + +// Adds subviews for the specified metric, the value of which will be displayed +// in |label|. +- (void)addMetricWithName:(NSString*)name + atIndex:(NSUInteger)index + usingLabel:(UILabel*)label { + // The width of the view for the metric's name. + const CGFloat kNameWidth = 150; + // The width of the view for each metric. + const CGFloat kMetricWidth = 100; + CGPoint nameOrigin = [self originForSubviewAtIndex:index]; + CGRect nameFrame = + CGRectMake(nameOrigin.x, nameOrigin.y, kNameWidth, [_font lineHeight]); + base::scoped_nsobject<UILabel> nameLabel( + [[UILabel alloc] initWithFrame:nameFrame]); + [nameLabel setText:[NSString stringWithFormat:@"%@: ", name]]; + [nameLabel setFont:_font]; + [self addSubview:nameLabel]; + label.frame = CGRectMake(CGRectGetMaxX(nameFrame), nameFrame.origin.y, + kMetricWidth, [_font lineHeight]); + [label setFont:_font]; + [label setTextAlignment:NSTextAlignmentRight]; + [self addSubview:label]; +} + +// Adds a subview for a button with the given title and target/action. +- (void)addButtonWithTitle:(NSString*)title + target:(id)target + action:(SEL)action + withOrigin:(CGPoint)origin { + base::scoped_nsobject<UIButton> button( + [[UIButton buttonWithType:UIButtonTypeSystem] retain]); + [button setTitle:title forState:UIControlStateNormal]; + [button titleLabel].font = _font; + [[button titleLabel] setTextAlignment:NSTextAlignmentCenter]; + [button sizeToFit]; + [button setFrame:CGRectMake(origin.x, origin.y, [button frame].size.width, + [_font lineHeight])]; + [button addTarget:target + action:action + forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:button]; +} + +// Adds subviews for a UI component with label and input text field. +// +// ------------------------- +// | labelText | <input> | +// ------------------------- +// +// The inputTarget/inputAction will be invoked when the user finishes editing +// in |input|. +- (void)addLabelWithText:(NSString*)labelText + input:(UITextField*)input + inputTarget:(id)inputTarget + inputAction:(SEL)inputAction + atIndex:(NSUInteger)index { + [self addLabelWithText:labelText + input:input + inputTarget:inputTarget + inputAction:inputAction + buttonWithTitle:nil + buttonTarget:nil + buttonAction:nil + atIndex:index]; +} + +// Adds subviews for a UI component with label, input text field and button. +// +// ------------------------------------- +// | labelText | <input> | <button> | +// ------------------------------------- +// +// The inputTarget/inputAction will be invoked when the user finishes editing +// in |input|. +- (void)addLabelWithText:(NSString*)labelText + input:(UITextField*)input + inputTarget:(id)inputTarget + inputAction:(SEL)inputAction + buttonWithTitle:(NSString*)buttonTitle + buttonTarget:(id)buttonTarget + buttonAction:(SEL)buttonAction + atIndex:(NSUInteger)index { + base::scoped_nsobject<UILabel> label( + [[UILabel alloc] initWithFrame:CGRectZero]); + if (labelText) { + [label setText:[NSString stringWithFormat:@"%@: ", labelText]]; + } + [label setFont:_font]; + [label sizeToFit]; + CGPoint labelOrigin = [self originForSubviewAtIndex:index]; + [label setFrame:CGRectOffset([label frame], labelOrigin.x, labelOrigin.y)]; + [self addSubview:label]; + if (input) { + // The width of the views for each input text field. + const CGFloat kInputWidth = 50; + input.frame = + CGRectMake(CGRectGetMaxX([label frame]) + kPadding, + [label frame].origin.y, kInputWidth, [_font lineHeight]); + input.font = _font; + input.backgroundColor = [UIColor whiteColor]; + input.delegate = self; + input.keyboardType = UIKeyboardTypeNumbersAndPunctuation; + input.adjustsFontSizeToFitWidth = YES; + input.textAlignment = NSTextAlignmentRight; + [input addTarget:inputTarget + action:inputAction + forControlEvents:UIControlEventEditingDidEnd]; + + [self addSubview:input]; + } + + if (buttonTitle) { + const CGFloat kButtonXOffset = + input ? CGRectGetMaxX(input.frame) : CGRectGetMaxX([label frame]); + CGPoint origin = + CGPointMake(kButtonXOffset + kPadding, [label frame].origin.y); + [self addButtonWithTitle:buttonTitle + target:buttonTarget + action:buttonAction + withOrigin:origin]; + } +} + +// Returns the CGPoint of the origin of the subview at |index|. +- (CGPoint)originForSubviewAtIndex:(NSUInteger)index { + return CGPointMake(kPadding, + (index + 1) * kPadding + index * [_font lineHeight]); +} + +#pragma mark Refresh callback + +// Updates content and ensures the view is visible. +- (void)refresh:(NSTimer*)timer { + [self.superview bringSubviewToFront:self]; + [self updateMemoryInfo]; +} + +#pragma mark Memory inspection + +// Updates the memory metrics shown. +- (void)updateMemoryInfo { + CGFloat value = memory_util::GetFreePhysicalBytes() / kNumBytesInMB; + [_physicalFreeMemoryLabel + setText:[NSString stringWithFormat:@"%.2f MB", value]]; + value = memory_util::GetRealMemoryUsedInBytes() / kNumBytesInMB; + [_realMemoryUsedLabel setText:[NSString stringWithFormat:@"%.2f MB", value]]; + value = memory_util::GetInternalVMBytes() / kNumBytesInMB; + [_xcodeGaugeLabel setText:[NSString stringWithFormat:@"%.2f MB", value]]; + value = memory_util::GetDirtyVMBytes() / kNumBytesInMB; + [_dirtyVirtualMemoryLabel + setText:[NSString stringWithFormat:@"%.2f MB", value]]; +} + +#pragma mark Memory Warning notification callback + +// Flashes the debugger to indicate memory warning. +- (void)lowMemoryWarningReceived:(NSNotification*)notification { + UIColor* originalColor = self.backgroundColor; + self.backgroundColor = + [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.9]; + [UIView animateWithDuration:1.0 + delay:0.0 + options:UIViewAnimationOptionAllowUserInteraction + animations:^{ + self.backgroundColor = originalColor; + } + completion:nil]; +} + +#pragma mark Rotation notification callback + +- (void)didMoveToSuperview { + UIView* superview = [self superview]; + if (superview) + [self setCenter:[superview center]]; +} + +- (void)adjustForOrientation:(NSNotification*)notification { + if (base::ios::IsRunningOnIOS8OrLater()) { + return; + } + UIInterfaceOrientation orientation = + [[UIApplication sharedApplication] statusBarOrientation]; + if (orientation == _currentOrientation) { + return; + } + _currentOrientation = orientation; + CGFloat angle; + switch (orientation) { + case UIInterfaceOrientationPortrait: + angle = 0; + break; + case UIInterfaceOrientationPortraitUpsideDown: + angle = M_PI; + break; + case UIInterfaceOrientationLandscapeLeft: + angle = -M_PI_2; + break; + case UIInterfaceOrientationLandscapeRight: + angle = M_PI_2; + break; + case UIInterfaceOrientationUnknown: + default: + angle = 0; + } + + // Since the debugger view is in screen coordinates and handles its own + // rotation via the |transform| property, the view's position after rotation + // can be unexpected and partially off-screen. Centering the view before + // rotating it ensures that the view remains within the bounds of the screen. + if (self.superview) { + self.center = self.superview.center; + } + self.transform = CGAffineTransformMakeRotation(angle); +} + +#pragma mark Keyboard notification callbacks + +// Ensures the debugger is visible by shifting it up as the keyboard animates +// in. +- (void)keyboardWillShow:(NSNotification*)notification { + NSDictionary* userInfo = [notification userInfo]; + NSValue* keyboardFrameValue = + [userInfo valueForKey:UIKeyboardFrameEndUserInfoKey]; + CGFloat keyboardHeight = CurrentKeyboardHeight(keyboardFrameValue); + + // Get the coord of the bottom of the debugger's frame. This is orientation + // dependent on iOS 7 because the debugger is in screen coords. + CGFloat bottomOfFrame = CGRectGetMaxY(self.frame); + if (!base::ios::IsRunningOnIOS8OrLater() && IsLandscape()) + bottomOfFrame = CGRectGetMaxX(self.frame); + + // Shift the debugger up by the "height" of the keyboard, but since the + // keyboard rect is in screen coords, use the orientation to find the height. + CGFloat distanceFromBottom = CurrentScreenHeight() - bottomOfFrame; + _keyboardOffset = -1 * fmax(0.0f, keyboardHeight - distanceFromBottom); + [self animateForKeyboardNotification:notification + withOffset:CGPointMake(0, _keyboardOffset)]; +} + +// Shifts the debugger back down when the keyboard is hidden. +- (void)keyboardWillHide:(NSNotification*)notification { + [self animateForKeyboardNotification:notification + withOffset:CGPointMake(0, -_keyboardOffset)]; +} + +- (void)animateForKeyboardNotification:(NSNotification*)notification + withOffset:(CGPoint)offset { + // Account for orientation. + offset = CGPointApplyAffineTransform(offset, self.transform); + // Normally this would use an animation block, but there is no API to + // convert the UIKeyboardAnimationCurveUserInfoKey's value from a + // UIViewAnimationCurve to a UIViewAnimationOption. Awesome! + NSDictionary* userInfo = [notification userInfo]; + [UIView beginAnimations:nil context:nullptr]; + [UIView setAnimationDuration: + [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; + NSInteger animationCurveKeyValue = + [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; + UIViewAnimationCurve animationCurve = + (UIViewAnimationCurve)animationCurveKeyValue; + [UIView setAnimationCurve:animationCurve]; + [UIView setAnimationBeginsFromCurrentState:YES]; + self.frame = CGRectOffset(self.frame, offset.x, offset.y); + [UIView commitAnimations]; +} + +#pragma mark Artificial memory bloat methods + +- (void)updateBloat { + double bloatSizeMB; + NSScanner* scanner = [NSScanner scannerWithString:[_bloatField text]]; + if (![scanner scanDouble:&bloatSizeMB] || bloatSizeMB < 0.0) { + bloatSizeMB = 0; + NSString* errorMessage = + [NSString stringWithFormat:@"Invalid value \"%@\" for bloat size.\n" + @"Must be a positive number.\n" + @"Resetting to %.1f MB", + [_bloatField text], bloatSizeMB]; + [self alert:errorMessage]; + [_bloatField setText:[NSString stringWithFormat:@"%.1f", bloatSizeMB]]; + } + const CGFloat kBloatSizeBytes = ceil(bloatSizeMB * kNumBytesInMB); + const uint64 kNumberOfBytes = static_cast<uint64>(kBloatSizeBytes); + _bloat.reset(kNumberOfBytes ? new uint8[kNumberOfBytes] : nullptr); + if (_bloat) { + memset(_bloat.get(), -1, kNumberOfBytes); // Occupy memory. + } else { + if (kNumberOfBytes) { + [self alert:@"Could not allocate memory."]; + } + } +} + +- (void)clearBloat { + [_bloatField setText:@"0"]; + [_bloatField resignFirstResponder]; + [self updateBloat]; +} + +#pragma mark Refresh interval methods + +- (void)updateRefreshInterval { + double refreshTimerValue; + NSScanner* scanner = [NSScanner scannerWithString:[_refreshField text]]; + if (![scanner scanDouble:&refreshTimerValue] || refreshTimerValue < 0.0) { + refreshTimerValue = 0.5; + NSString* errorMessage = [NSString + stringWithFormat:@"Invalid value \"%@\" for refresh interval.\n" + @"Must be a positive number.\n" @"Resetting to %.1f", + [_refreshField text], refreshTimerValue]; + [self alert:errorMessage]; + [_refreshField + setText:[NSString stringWithFormat:@"%.1f", refreshTimerValue]]; + return; + } + [_refreshTimer invalidate]; + _refreshTimer.reset( + [[NSTimer scheduledTimerWithTimeInterval:refreshTimerValue + target:self + selector:@selector(refresh:) + userInfo:nil + repeats:YES] retain]); +} + +#pragma mark Memory warning interval methods + +// Since _performMemoryWarning is a private API it can't be compiled into +// official builds. +// TODO(lliabraa): Figure out how to support memory warnings (or something +// like them) in official builds. +#if CHROMIUM_BUILD +- (void)updateMemoryWarningInterval { + [_memoryWarningTimer invalidate]; + double timerValue; + NSString* text = [_continuousMemoryWarningField text]; + NSScanner* scanner = [NSScanner scannerWithString:text]; + BOOL valueFound = [scanner scanDouble:&timerValue]; + // If the text field is empty or contains 0, return early to turn off + // continuous memory warnings. + if (![text length] || timerValue == 0.0) { + return; + } + // If no value could be parsed or a non-positive value was found, throw up an + // error message and return early to turn off continuous memory warnings. + if (!valueFound || timerValue <= 0.0) { + NSString* errorMessage = [NSString + stringWithFormat:@"Invalid value \"%@\" for memory warning interval.\n" + @"Must be a positive number.\n" + @"Turning off continuous memory warnings", + text]; + [self alert:errorMessage]; + [_continuousMemoryWarningField setText:@""]; + return; + } + // If a valid value was found have the timer start triggering continuous + // memory warnings. + _memoryWarningTimer.reset( + [[NSTimer scheduledTimerWithTimeInterval:timerValue + target:[UIApplication sharedApplication] + selector:@selector(_performMemoryWarning) + userInfo:nil + repeats:YES] retain]); +} +#endif // CHROMIUM_BUILD + +#pragma mark UITextViewDelegate methods + +// Dismisses the keyboard if the user hits return. +- (BOOL)textFieldShouldReturn:(UITextField*)textField { + [textField resignFirstResponder]; + return YES; +} + +#pragma mark UIResponder methods + +// Allows the debugger to be dragged around the screen. +- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { + UITouch* touch = [touches anyObject]; + CGPoint start = [touch previousLocationInView:self]; + CGPoint end = [touch locationInView:self]; + CGPoint offset = CGPointMake(end.x - start.x, end.y - start.y); + offset = CGPointApplyAffineTransform(offset, self.transform); + self.frame = CGRectOffset(self.frame, offset.x, offset.y); +} + +#pragma mark Error handling + +// Shows an alert with the given |errorMessage|. +- (void)alert:(NSString*)errorMessage { + UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error" + message:errorMessage + delegate:self + cancelButtonTitle:@"OK" + otherButtonTitles:nil, nil]; + [alert show]; +} + +@end
diff --git a/ios/chrome/browser/memory/memory_debugger_manager.h b/ios/chrome/browser/memory/memory_debugger_manager.h new file mode 100644 index 0000000..4cd7941 --- /dev/null +++ b/ios/chrome/browser/memory/memory_debugger_manager.h
@@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_MEMORY_MEMORY_DEBUGGER_MANAGER_H_ +#define IOS_CHROME_BROWSER_MEMORY_MEMORY_DEBUGGER_MANAGER_H_ + +#import <Foundation/Foundation.h> + +class PrefRegistrySimple; +class PrefService; +@class UIView; + +// A class to manage the life cycle of a MemoryDebugger instance. +// +// A MemoryDebugger's existence is controlled by a pref in local state, so the +// MemoryDebuggerManager listens for changes to that pref and instantiates or +// frees the debugger as appropriate. +@interface MemoryDebuggerManager : NSObject +// Designated initializer. +- (instancetype)initWithView:(UIView*)view prefs:(PrefService*)prefs; +// Registers local state preferences. ++ (void)registerLocalState:(PrefRegistrySimple*)registry; +@end + +#endif // IOS_CHROME_BROWSER_MEMORY_MEMORY_DEBUGGER_MANAGER_H_
diff --git a/ios/chrome/browser/memory/memory_debugger_manager.mm b/ios/chrome/browser/memory/memory_debugger_manager.mm new file mode 100644 index 0000000..e9e9acb --- /dev/null +++ b/ios/chrome/browser/memory/memory_debugger_manager.mm
@@ -0,0 +1,72 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/memory/memory_debugger_manager.h" + +#include "base/ios/weak_nsobject.h" +#import "base/mac/bind_objc_block.h" +#include "base/mac/scoped_nsobject.h" +#include "base/prefs/pref_member.h" +#include "base/prefs/pref_registry_simple.h" +#include "base/prefs/pref_service.h" +#import "ios/chrome/browser/memory/memory_debugger.h" +#import "ios/chrome/browser/pref_names.h" + +@implementation MemoryDebuggerManager { + UIView* debuggerParentView_; // weak + base::scoped_nsobject<MemoryDebugger> memoryDebugger_; + BooleanPrefMember showMemoryDebugger_; +} + +- (instancetype)initWithView:(UIView*)debuggerParentView + prefs:(PrefService*)prefs { + if (self = [super init]) { + debuggerParentView_ = debuggerParentView; + + // Set up the callback for when the pref to show/hide the debugger changes. + base::WeakNSObject<MemoryDebuggerManager> weakSelf(self); + base::Closure callback = base::BindBlock(^{ + base::scoped_nsobject<MemoryDebuggerManager> strongSelf( + [weakSelf retain]); + if (strongSelf) { + [self onShowMemoryDebuggingToolsChange]; + } + }); + showMemoryDebugger_.Init(prefs::kShowMemoryDebuggingTools, prefs, callback); + // Invoke the pref change callback once to show the debugger on start up, + // if necessary. + [self onShowMemoryDebuggingToolsChange]; + } + return self; +} + +- (void)dealloc { + [self tearDownDebugger]; + [super dealloc]; +} + +#pragma mark - Pref-handling methods + +// Registers local state prefs. ++ (void)registerLocalState:(PrefRegistrySimple*)registry { + registry->RegisterBooleanPref(prefs::kShowMemoryDebuggingTools, false); +} + +// Shows or hides the debugger when the pref changes. +- (void)onShowMemoryDebuggingToolsChange { + if (showMemoryDebugger_.GetValue()) { + memoryDebugger_.reset([[MemoryDebugger alloc] init]); + [debuggerParentView_ addSubview:memoryDebugger_]; + } else { + [self tearDownDebugger]; + } +} + +// Tears down the debugger so it can be deallocated. +- (void)tearDownDebugger { + [memoryDebugger_ invalidateTimers]; + [memoryDebugger_ removeFromSuperview]; + memoryDebugger_.reset(); +} +@end
diff --git a/ios/chrome/browser/memory/memory_metrics.cc b/ios/chrome/browser/memory/memory_metrics.cc new file mode 100644 index 0000000..360c533f --- /dev/null +++ b/ios/chrome/browser/memory/memory_metrics.cc
@@ -0,0 +1,89 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/memory/memory_metrics.h" + +#include <mach/mach.h> + +#include "base/logging.h" +#include "base/process/process_handle.h" +#include "base/process/process_metrics.h" + +#ifdef ARCH_CPU_64_BITS +#define cr_vm_region vm_region_64 +#else +#define cr_vm_region vm_region +#endif + +namespace { +// The number of pages returned by host_statistics and vm_region are a count +// of pages of 4096 bytes even when running on arm64 but the constants that +// are exposed (vm_page_size, VM_PAGE_SIZE, host_page_size) are all equals to +// 16384 bytes. So we define our own constant here to convert from page count +// to bytes. +const uint64_t kVMPageSize = 4096; +} + +namespace memory_util { + +uint64 GetFreePhysicalBytes() { + vm_statistics_data_t vmstat; + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + kern_return_t result = + host_statistics(mach_host_self(), HOST_VM_INFO, + reinterpret_cast<host_info_t>(&vmstat), &count); + if (result != KERN_SUCCESS) { + LOG(ERROR) << "Calling host_statistics failed."; + return 0; + } + return vmstat.free_count * kVMPageSize; +} + +uint64 GetRealMemoryUsedInBytes() { + base::ProcessHandle process_handle = base::GetCurrentProcessHandle(); + scoped_ptr<base::ProcessMetrics> process_metrics( + base::ProcessMetrics::CreateProcessMetrics(process_handle)); + return static_cast<uint64>(process_metrics->GetWorkingSetSize()); +} + +uint64 GetDirtyVMBytes() { + // Iterate over all VM regions and sum their dirty pages. + unsigned int total_dirty_pages = 0; + vm_size_t vm_size = 0; + kern_return_t result; + for (vm_address_t address = MACH_VM_MIN_ADDRESS;; address += vm_size) { + vm_region_extended_info_data_t info; + mach_msg_type_number_t info_count = VM_REGION_EXTENDED_INFO_COUNT; + mach_port_t object_name; + result = cr_vm_region( + mach_task_self(), &address, &vm_size, VM_REGION_EXTENDED_INFO, + reinterpret_cast<vm_region_info_t>(&info), &info_count, &object_name); + if (result == KERN_INVALID_ADDRESS) { + // The end of the address space has been reached. + break; + } else if (result != KERN_SUCCESS) { + LOG(ERROR) << "Calling vm_region failed with code: " << result; + break; + } else { + total_dirty_pages += info.pages_dirtied; + } + } + return total_dirty_pages * kVMPageSize; +} + +uint64 GetInternalVMBytes() { + task_vm_info_data_t task_vm_info; + mach_msg_type_number_t count = TASK_VM_INFO_COUNT; + kern_return_t result = + task_info(mach_task_self(), TASK_VM_INFO, + reinterpret_cast<task_info_t>(&task_vm_info), &count); + if (result != KERN_SUCCESS) { + LOG(ERROR) << "Calling task_info failed."; + return 0; + } + + return static_cast<uint64>(task_vm_info.internal); +} + +} // namespace memory_util
diff --git a/ios/chrome/browser/memory/memory_metrics.h b/ios/chrome/browser/memory/memory_metrics.h new file mode 100644 index 0000000..7903848 --- /dev/null +++ b/ios/chrome/browser/memory/memory_metrics.h
@@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_MEMORY_MEMORY_METRICS_H_ +#define IOS_CHROME_BROWSER_MEMORY_MEMORY_METRICS_H_ + +#include "base/basictypes.h" + +namespace memory_util { +// "Physical Free" memory metric. This corresponds to the "Physical Memory Free" +// value reported by the Memory Monitor in Instruments. +uint64 GetFreePhysicalBytes(); + +// "Real Memory Used" memory metric. This corresponds to the "Real Memory" value +// reported for the app by the Memory Monitor in Instruments. +uint64 GetRealMemoryUsedInBytes(); + +// "Xcode Gauge" memory metric. This corresponds to the "Memory" value reported +// for the app by the Debug Navigator in Xcode. Only supported in iOS 7 and +// later. +uint64 GetInternalVMBytes(); + +// "Dirty VM" memory metric. This corresponds to the "Dirty Size" value reported +// for the app by the VM Tracker in Instruments. +uint64 GetDirtyVMBytes(); +} // namespace memory_util + +#endif // IOS_CHROME_BROWSER_MEMORY_MEMORY_METRICS_H_
diff --git a/ios/chrome/browser/pref_names.cc b/ios/chrome/browser/pref_names.cc index 529a093..4ef5ece 100644 --- a/ios/chrome/browser/pref_names.cc +++ b/ios/chrome/browser/pref_names.cc
@@ -33,4 +33,8 @@ // The preferred SSO user for wallet payments. const char kPaymentsPreferredUserId[] = "ios.payments.preferred_user_id"; +// True if the memory debugging tools should be visible. +extern const char kShowMemoryDebuggingTools[] = + "ios.memory.show_debugging_tools"; + } // namespace prefs
diff --git a/ios/chrome/browser/pref_names.h b/ios/chrome/browser/pref_names.h index cda81cd..95ede81 100644 --- a/ios/chrome/browser/pref_names.h +++ b/ios/chrome/browser/pref_names.h
@@ -20,6 +20,7 @@ extern const char kIosBookmarkFolderDefault[]; extern const char kIosBookmarkPromoAlreadySeen[]; extern const char kPaymentsPreferredUserId[]; +extern const char kShowMemoryDebuggingTools[]; } // namespace prefs
diff --git a/ios/chrome/browser/ui/OWNERS b/ios/chrome/browser/ui/OWNERS new file mode 100644 index 0000000..7c547ca --- /dev/null +++ b/ios/chrome/browser/ui/OWNERS
@@ -0,0 +1,2 @@ +pkl@chromium.org +rohitrao@chromium.org
diff --git a/ios/chrome/browser/ui/background_generator.h b/ios/chrome/browser/ui/background_generator.h new file mode 100644 index 0000000..00f433d --- /dev/null +++ b/ios/chrome/browser/ui/background_generator.h
@@ -0,0 +1,27 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_BACKGROUND_GENERATOR_H_ +#define IOS_CHROME_BROWSER_UI_BACKGROUND_GENERATOR_H_ + +#include <UIKit/UIKit.h> + +// Returns a UIImage of size |backgroundRect| with a radial gradient image at +// |centerPoint| and radiates outwards to a radius of |radius|. The gradient +// starts from |centerColor| at |centerPoint| to |outsideColor| at the end of +// |radius|. |tileImage| is tiled over the entire image and |logoImage| is +// rendered at |centerPoint|. +// |tileImage| and |logoImage| may be nil. +UIImage* GetRadialGradient(CGRect backgroundRect, + CGPoint centerPoint, + CGFloat radius, + CGFloat centerColor, + CGFloat outsideColor, + UIImage* tileImage, + UIImage* logoImage); + +// Installs the stack view/empty tab view background in |view|. +void InstallBackgroundInView(UIView* view); + +#endif // IOS_CHROME_BROWSER_UI_BACKGROUND_GENERATOR_H_
diff --git a/ios/chrome/browser/ui/background_generator.mm b/ios/chrome/browser/ui/background_generator.mm new file mode 100644 index 0000000..a115d83 --- /dev/null +++ b/ios/chrome/browser/ui/background_generator.mm
@@ -0,0 +1,57 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/background_generator.h" + +#import <QuartzCore/QuartzCore.h> + +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#include "base/mac/scoped_cftyperef.h" +#import "base/mac/scoped_nsobject.h" +#import "ios/chrome/browser/ui/ui_util.h" + +// This is a utility function that may be used as a standalone helper function +// to generate a radial gradient UIImage. +UIImage* GetRadialGradient(CGRect backgroundRect, + CGPoint centerPoint, + CGFloat radius, + CGFloat centerColor, + CGFloat outsideColor, + UIImage* tileImage, + UIImage* logoImage) { + UIGraphicsBeginImageContextWithOptions(backgroundRect.size, YES, 0); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGFloat gradient_colors[4] = {centerColor, 1.0, outsideColor, 1.0}; + const size_t kColorCount = 2; + base::ScopedCFTypeRef<CGColorSpaceRef> grey_space( + CGColorSpaceCreateDeviceGray()); + DCHECK_EQ(2u, CGColorSpaceGetNumberOfComponents(grey_space)); + base::ScopedCFTypeRef<CGGradientRef> gradient( + CGGradientCreateWithColorComponents(grey_space, gradient_colors, nullptr, + kColorCount)); + CGContextDrawRadialGradient(context, gradient, centerPoint, 0, centerPoint, + radius, kCGGradientDrawsAfterEndLocation); + if (tileImage) + [tileImage drawAsPatternInRect:backgroundRect]; + if (logoImage) { + CGPoint corner = AlignPointToPixel( + CGPointMake(centerPoint.x - logoImage.size.width / 2.0, + centerPoint.y - logoImage.size.height / 2.0)); + [logoImage drawAtPoint:corner]; + } + UIImage* background = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return background; +} + +void InstallBackgroundInView(UIView* view) { + UIImageView* imageView = + [[[UIImageView alloc] initWithFrame:view.bounds] autorelease]; + imageView.image = [UIImage imageNamed:@"stack_view_background_noise.jpg"]; + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.autoresizingMask = + UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + [view insertSubview:imageView atIndex:0]; +}
diff --git a/ios/chrome/browser/ui/file_locations.h b/ios/chrome/browser/ui/file_locations.h new file mode 100644 index 0000000..ddba28e --- /dev/null +++ b/ios/chrome/browser/ui/file_locations.h
@@ -0,0 +1,14 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FILE_LOCATIONS_H_ +#define IOS_CHROME_BROWSER_UI_FILE_LOCATIONS_H_ + +#include <string> + +// Returns file name for Terms of Service text localized for the application +// locale. +std::string GetTermsOfServicePath(); + +#endif // IOS_CHROME_BROWSER_UI_FILE_LOCATIONS_H_
diff --git a/ios/chrome/browser/ui/file_locations.mm b/ios/chrome/browser/ui/file_locations.mm new file mode 100644 index 0000000..5a5e7de --- /dev/null +++ b/ios/chrome/browser/ui/file_locations.mm
@@ -0,0 +1,83 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/file_locations.h" + +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/chrome/browser/application_context.h" + +namespace { +// English is the default locale for the Terms of Service. +const char kEnglishLocale[] = "en"; +// The prefix of the Chrome Terms of Service file name. +const char kChromeTosFilePrefix[] = "terms"; +// The file name extension for HTML files. +const char kHtmlFileExtension[] = "html"; + +// Checks that the requested file exists in the application's resource +// bundle and returns the filename. Returns an empty string if resource does not +// exist. +std::string FindFileInResource(const std::string& base_name, + const std::string& language, + const std::string& ext) { + std::string resource_file(base_name + "_" + language); + BOOL exists = + [base::mac::FrameworkBundle() + URLForResource:[NSString stringWithUTF8String:resource_file.c_str()] + withExtension:[NSString stringWithUTF8String:ext.c_str()]] != nil; + return exists ? resource_file + "." + ext : ""; +} + +} // namespace + +// iOS uses certain locale initials that are different from Chrome's. +// Most notably, "pt" means "pt-BR" (Brazillian Portuguese). This +// function normalizes the locale into language-region code used by +// Chrome. +std::string GetIOSLocaleMapping(const std::string& locale) { + if (locale == "pt") // Brazillian Portuguese + return "pt-BR"; + else if (locale == "zh-Hans") // Chinese Simplified script + return "zh-CN"; + else if (locale == "zh-Hant") // Chinese Traditional script + return "zh-TW"; + else if (locale == "es-MX") + return "es-419"; + return locale; +} + +// Returns a filename based on the base file name and file extension and +// localized for the given locale. Checks the existence of the file based on +// |locale| as follows: +// * if there is a file for file_<locale>.<ext> +// * if not, check the language part as follows file_<locale[0..]>.<ext> +// * when all else fails, use the English locale, e.g. file_en.<ext>, which +// must exist. +// |locale| must be a valid Chrome locale as defined in file +// ui/base/l10n/l10n_util.cc. This corresponds to a language or a country code, +// e.g. "en", "en-US", "fr", etc. +std::string GetLocalizedFileName(const std::string& base_name, + const std::string& locale, + const std::string& ext) { + std::string mappedLocale = GetIOSLocaleMapping(locale); + std::string resource_file = FindFileInResource(base_name, mappedLocale, ext); + if (resource_file.empty() && mappedLocale.length() > 2 && + mappedLocale[2] == '-') { + std::string language = mappedLocale.substr(0, 2); + resource_file = FindFileInResource(base_name, language, ext); + } + if (resource_file.empty()) { + // Default to English if resource is still not found. + resource_file = FindFileInResource(base_name, kEnglishLocale, ext); + } + DCHECK(!resource_file.empty()); + return resource_file; +} + +std::string GetTermsOfServicePath() { + const std::string& locale = GetApplicationContext()->GetApplicationLocale(); + return GetLocalizedFileName(kChromeTosFilePrefix, locale, kHtmlFileExtension); +}
diff --git a/ios/chrome/browser/ui/native_content_controller.h b/ios/chrome/browser/ui/native_content_controller.h new file mode 100644 index 0000000..f084d2d --- /dev/null +++ b/ios/chrome/browser/ui/native_content_controller.h
@@ -0,0 +1,46 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_NATIVE_CONTENT_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_NATIVE_CONTENT_CONTROLLER_H_ + +#import <Foundation/Foundation.h> + +#import "ios/web/public/web_state/crw_native_content.h" +#include "url/gurl.h" + +@class UIView; + +// Abstract base class for controllers that implement the behavior for native +// views that are presented inside the web content area. Automatically removes +// |view| from the view hierarchy when it is destroyed. Subclasses are +// responsible for setting the view (usually through loading a nib) and the +// page title. +@interface NativeContentController : NSObject<CRWNativeContent> { + @protected + UIView* _view; // Top-level view. + NSString* _title; + GURL _url; +} + +@property(nonatomic, retain) IBOutlet UIView* view; +@property(nonatomic, copy) NSString* title; +@property(nonatomic, readonly, assign) const GURL& url; + +// Initializer that attempts to load the nib specified in |nibName| for +// |url|, which may be nil. +- (instancetype)initWithNibName:(NSString*)nibName url:(const GURL&)url; + +// Initializer with the |url| to be loaded. +- (instancetype)initWithURL:(const GURL&)url; + +// Called when memory is low and this is not the foreground tab. Release +// anything (such as views) that can be easily re-created to free up RAM. +// Subclasses that override this method should always call +// [super handleLowMemory]. +- (void)handleLowMemory; + +@end + +#endif // IOS_CHROME_BROWSER_UI_NATIVE_CONTENT_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/native_content_controller.mm b/ios/chrome/browser/ui/native_content_controller.mm new file mode 100644 index 0000000..0d40cfc --- /dev/null +++ b/ios/chrome/browser/ui/native_content_controller.mm
@@ -0,0 +1,60 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/native_content_controller.h" + +#import <UIKit/UIKit.h> + +#include "base/mac/bundle_locations.h" +#import "base/mac/foundation_util.h" +#include "base/mac/objc_property_releaser.h" + +@implementation NativeContentController { + base::mac::ObjCPropertyReleaser _propertyReleaser_NativeContentController; +} + +@synthesize view = _view; +@synthesize title = _title; +@synthesize url = _url; + +- (instancetype)initWithNibName:(NSString*)nibName url:(const GURL&)url { + self = [super init]; + if (self) { + _propertyReleaser_NativeContentController.Init( + self, [NativeContentController class]); + [base::mac::FrameworkBundle() loadNibNamed:nibName owner:self options:nil]; + _url = url; + } + return self; +} + +- (instancetype)initWithURL:(const GURL&)url { + self = [super init]; + if (self) { + _propertyReleaser_NativeContentController.Init( + self, [NativeContentController class]); + _url = url; + } + return self; +} + +- (void)dealloc { + [_view removeFromSuperview]; + [super dealloc]; +} + +- (void)handleLowMemory { + // TODO(pinkerton): What should this do? Toss the view? +} + +- (BOOL)isViewAlive { + // TODO(pinkerton): See handleLowMemory above. + return YES; +} + +- (void)reload { + // Not implemented in base class. +} + +@end
diff --git a/ios/chrome/browser/ui/orientation_limiting_navigation_controller.h b/ios/chrome/browser/ui/orientation_limiting_navigation_controller.h new file mode 100644 index 0000000..e687823 --- /dev/null +++ b/ios/chrome/browser/ui/orientation_limiting_navigation_controller.h
@@ -0,0 +1,14 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef IOS_CHROME_BROWSER_UI_ORIENTATION_LIMITING_NAVIGATION_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_ORIENTATION_LIMITING_NAVIGATION_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +// A navigation controller that supports only |UIInterfaceOrientationPortrait| +// orientation on iPhone and supports all orientations on iPad. +@interface OrientationLimitingNavigationController : UINavigationController +@end + +#endif // IOS_CHROME_BROWSER_UI_ORIENTATION_LIMITING_NAVIGATION_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/orientation_limiting_navigation_controller.mm b/ios/chrome/browser/ui/orientation_limiting_navigation_controller.mm new file mode 100644 index 0000000..4a5e28c --- /dev/null +++ b/ios/chrome/browser/ui/orientation_limiting_navigation_controller.mm
@@ -0,0 +1,26 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/orientation_limiting_navigation_controller.h" + +#include "base/logging.h" +#include "ios/chrome/browser/ui/ui_util.h" + +@implementation OrientationLimitingNavigationController + +- (NSUInteger)supportedInterfaceOrientations { + return IsIPadIdiom() ? [super supportedInterfaceOrientations] + : UIInterfaceOrientationMaskPortrait; +} + +- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { + return IsIPadIdiom() ? [super preferredInterfaceOrientationForPresentation] + : UIInterfaceOrientationPortrait; +} + +- (BOOL)shouldAutorotate { + return IsIPadIdiom() ? [super shouldAutorotate] : NO; +} + +@end
diff --git a/ios/chrome/browser/ui/show_mail_composer_util.h b/ios/chrome/browser/ui/show_mail_composer_util.h new file mode 100644 index 0000000..34c9fb0 --- /dev/null +++ b/ios/chrome/browser/ui/show_mail_composer_util.h
@@ -0,0 +1,20 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SHOW_MAIL_COMPOSER_UTIL_H_ +#define IOS_CHROME_BROWSER_UI_SHOW_MAIL_COMPOSER_UTIL_H_ + +#include "base/files/file_path.h" +#include "base/strings/string16.h" + +// Shows the mail composer UI with the specified parameters. +void ShowMailComposer(const base::string16& to_recipient, + const base::string16& subject, + const base::string16& body, + const base::string16& title, + const base::FilePath& text_file_to_attach, + int email_not_configured_alert_title_id, + int email_not_configured_alert_message_id); + +#endif // IOS_CHROME_BROWSER_UI_SHOW_MAIL_COMPOSER_UTIL_H_
diff --git a/ios/chrome/browser/ui/show_mail_composer_util.mm b/ios/chrome/browser/ui/show_mail_composer_util.mm new file mode 100644 index 0000000..2d9624c5 --- /dev/null +++ b/ios/chrome/browser/ui/show_mail_composer_util.mm
@@ -0,0 +1,33 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/show_mail_composer_util.h" + +#include <UIKit/UIKit.h> + +#include "base/logging.h" +#include "base/mac/scoped_nsobject.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#include "ios/chrome/browser/ui/commands/show_mail_composer_command.h" + +void ShowMailComposer(const base::string16& to_recipient, + const base::string16& subject, + const base::string16& body, + const base::string16& title, + const base::FilePath& text_file_to_attach, + int email_not_configured_alert_title_id, + int email_not_configured_alert_message_id) { + base::scoped_nsobject<ShowMailComposerCommand> + command([[ShowMailComposerCommand alloc] + initWithToRecipient:base::SysUTF16ToNSString(to_recipient) + subject:base::SysUTF16ToNSString(subject) + body:base::SysUTF16ToNSString(body) + emailNotConfiguredAlertTitleId:email_not_configured_alert_title_id + emailNotConfiguredAlertMessageId:email_not_configured_alert_message_id]); + [command setTextFileToAttach:text_file_to_attach]; + UIWindow* main_window = [[UIApplication sharedApplication] keyWindow]; + DCHECK(main_window); + [main_window.rootViewController chromeExecuteCommand:command]; +}
diff --git a/ios/chrome/browser/ui/show_privacy_settings_util.h b/ios/chrome/browser/ui/show_privacy_settings_util.h new file mode 100644 index 0000000..a0f5d908 --- /dev/null +++ b/ios/chrome/browser/ui/show_privacy_settings_util.h
@@ -0,0 +1,11 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +#ifndef IOS_CHROME_BROWSER_UI_SHOW_PRIVACY_SETTINGS_UTIL_H_ +#define IOS_CHROME_BROWSER_UI_SHOW_PRIVACY_SETTINGS_UTIL_H_ + +// Shows the privacy settings UI. +void ShowClearBrowsingData(); + +#endif // IOS_CHROME_BROWSER_UI_SHOW_PRIVACY_SETTINGS_UTIL_H_
diff --git a/ios/chrome/browser/ui/show_privacy_settings_util.mm b/ios/chrome/browser/ui/show_privacy_settings_util.mm new file mode 100644 index 0000000..2d83683e --- /dev/null +++ b/ios/chrome/browser/ui/show_privacy_settings_util.mm
@@ -0,0 +1,18 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/show_privacy_settings_util.h" + +#include "base/mac/scoped_nsobject.h" +#include "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" +#import "ios/chrome/browser/ui/commands/generic_chrome_command.h" +#include "ios/chrome/browser/ui/commands/ios_command_ids.h" + +void ShowClearBrowsingData() { + base::scoped_nsobject<GenericChromeCommand> command( + [[GenericChromeCommand alloc] init]); + [command setTag:IDC_SHOW_PRIVACY_SETTINGS]; + UIWindow* main_window = [[UIApplication sharedApplication] keyWindow]; + [main_window chromeExecuteCommand:command]; +}
diff --git a/ios/chrome/browser/ui/side_swipe_gesture_recognizer.h b/ios/chrome/browser/ui/side_swipe_gesture_recognizer.h new file mode 100644 index 0000000..3e97dda --- /dev/null +++ b/ios/chrome/browser/ui/side_swipe_gesture_recognizer.h
@@ -0,0 +1,26 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SIDE_SWIPE_GESTURE_RECOGNIZER_H_ +#define IOS_CHROME_BROWSER_UI_SIDE_SWIPE_GESTURE_RECOGNIZER_H_ + +#import <UIKit/UIGestureRecognizerSubclass.h> +#import <UIKit/UIKit.h> + +// This gesture recognizer is used because the default swipe gesture recognizer +// is too restrictive. The default swipe requires a particular velocity and +// distance that Chrome does not require. +// Another benefit of using a custom gesture recognizer is it can fail faster, +// so recognizers that depend on this recognizer can begin faster. +@interface SideSwipeGestureRecognizer : UIPanGestureRecognizer + +// The distance from the edge of the screen in which a side swipe can start. +@property(nonatomic, assign) CGFloat swipeEdge; +// The distance from the edge of the screen from which a gesture starts. +@property(readonly, nonatomic) CGFloat swipeOffset; +@property(nonatomic, assign) UISwipeGestureRecognizerDirection direction; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SIDE_SWIPE_GESTURE_RECOGNIZER_H_
diff --git a/ios/chrome/browser/ui/side_swipe_gesture_recognizer.mm b/ios/chrome/browser/ui/side_swipe_gesture_recognizer.mm new file mode 100644 index 0000000..66cb5753 --- /dev/null +++ b/ios/chrome/browser/ui/side_swipe_gesture_recognizer.mm
@@ -0,0 +1,106 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h" + +#include <cmath> + +#include "base/logging.h" + +namespace { + +// The absolute maximum swipe angle from |x = y| for a swipe to begin. +CGFloat kMaxSwipeYAngle = 65; +// The distance between touches for a swipe to begin. +CGFloat kMinSwipeXThreshold = 4; + +} // namespace + +@implementation SideSwipeGestureRecognizer { + // Starting point of swipe. + CGPoint _startPoint; + // Expected direction of the swipe, based on starting point. + UISwipeGestureRecognizerDirection _direction; +} + +@synthesize swipeEdge = _swipeEdge; +@synthesize direction = _direction; +@synthesize swipeOffset = _swipeOffset; + +// To quickly avoid interference with other gesture recognizers, fail +// immediately if the touches aren't at the edge of the touched view. +- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { + [super touchesBegan:touches withEvent:event]; + UITouch* touch = [[event allTouches] anyObject]; + CGPoint location = [touch locationInView:self.view]; + if (location.x > _swipeEdge && + location.x < CGRectGetMaxX([self.view bounds]) - _swipeEdge) { + self.state = UIGestureRecognizerStateFailed; + } else { + if (location.x < _swipeEdge) { + _direction = UISwipeGestureRecognizerDirectionRight; + } else { + _direction = UISwipeGestureRecognizerDirectionLeft; + } + _startPoint = location; + } +} + +- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { + // Revert to normal pan gesture recognizer characteristics after state began. + if (self.state != UIGestureRecognizerStatePossible) { + [super touchesMoved:touches withEvent:event]; + return; + } + + // Only one touch. + if ([[event allTouches] count] > 1) { + self.state = UIGestureRecognizerStateFailed; + return; + } + + // Don't swipe at an angle greater than |kMaxSwipeYAngle|. + UITouch* touch = [[event allTouches] anyObject]; + CGPoint currentPoint = [touch locationInView:self.view]; + CGFloat dy = currentPoint.y - _startPoint.y; + CGFloat dx = std::abs(currentPoint.x - _startPoint.x); + CGFloat degrees = std::fabs(std::atan2(dy, dx) * 180 / CGFloat(M_PI)); + if (degrees > kMaxSwipeYAngle) { + self.state = UIGestureRecognizerStateFailed; + return; + } + + // Don't recognize swipe in the wrong direction. + if ((_direction == UISwipeGestureRecognizerDirectionRight && + currentPoint.x - _startPoint.x < 0) || + (_direction == UISwipeGestureRecognizerDirectionLeft && + currentPoint.x - _startPoint.x > 0)) { + self.state = UIGestureRecognizerStateFailed; + return; + } + + // Begin recognizer after |kMinSwipeXThreshold| distance swiped. + if (std::abs(currentPoint.x - _startPoint.x) > kMinSwipeXThreshold) { + if (_direction == UISwipeGestureRecognizerDirectionRight) { + _swipeOffset = currentPoint.x; + } else { + _swipeOffset = -(CGRectGetMaxX([self.view bounds]) - currentPoint.x); + } + + self.state = UIGestureRecognizerStateBegan; + return; + } +} + +- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { + _startPoint = CGPointZero; + [super touchesEnded:touches withEvent:event]; +} + +- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { + _startPoint = CGPointZero; + [super touchesCancelled:touches withEvent:event]; +} + +@end
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index 6a221ecc..b2029dc 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp
@@ -105,6 +105,12 @@ 'browser/infobars/infobar_manager_impl.h', 'browser/infobars/infobar_utils.h', 'browser/infobars/infobar_utils.mm', + 'browser/memory/memory_debugger.h', + 'browser/memory/memory_debugger.mm', + 'browser/memory/memory_debugger_manager.h', + 'browser/memory/memory_debugger_manager.mm', + 'browser/memory/memory_metrics.cc', + 'browser/memory/memory_metrics.h', 'browser/net/chrome_cookie_store_ios_client.h', 'browser/net/chrome_cookie_store_ios_client.mm', 'browser/net/image_fetcher.h', @@ -148,6 +154,8 @@ 'browser/translate/translate_service_ios.h', 'browser/ui/animation_util.h', 'browser/ui/animation_util.mm', + 'browser/ui/background_generator.h', + 'browser/ui/background_generator.mm', 'browser/ui/commands/UIKit+ChromeExecuteCommand.h', 'browser/ui/commands/UIKit+ChromeExecuteCommand.mm', 'browser/ui/commands/clear_browsing_data_command.h', @@ -163,10 +171,22 @@ 'browser/ui/commands/show_accounts_settings_command.mm', 'browser/ui/commands/show_mail_composer_command.h', 'browser/ui/commands/show_mail_composer_command.mm', + 'browser/ui/file_locations.h', + 'browser/ui/file_locations.mm', 'browser/ui/image_util.h', 'browser/ui/image_util.mm', + 'browser/ui/native_content_controller.h', + 'browser/ui/native_content_controller.mm', + 'browser/ui/orientation_limiting_navigation_controller.h', + 'browser/ui/orientation_limiting_navigation_controller.mm', 'browser/ui/reversed_animation.h', 'browser/ui/reversed_animation.mm', + 'browser/ui/show_mail_composer_util.h', + 'browser/ui/show_mail_composer_util.mm', + 'browser/ui/show_privacy_settings_util.h', + 'browser/ui/show_privacy_settings_util.mm', + 'browser/ui/side_swipe_gesture_recognizer.h', + 'browser/ui/side_swipe_gesture_recognizer.mm', 'browser/ui/ui_util.h', 'browser/ui/ui_util.mm', 'browser/ui/uikit_ui_util.h',
diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp index bbc1b83..35ca42b 100644 --- a/ios/web/ios_web.gyp +++ b/ios/web/ios_web.gyp
@@ -96,11 +96,9 @@ 'public/web_state/crw_web_view_proxy.h' 'public/web_state/crw_web_view_scroll_view_proxy.h' 'public/web_state/js/crw_js_base_manager.h', - 'public/web_state/js/crw_js_early_script_manager.h', 'public/web_state/js/crw_js_injection_evaluator.h', 'public/web_state/js/crw_js_injection_manager.h', 'public/web_state/js/crw_js_injection_receiver.h', - 'public/web_state/js/crw_js_message_manager.h', 'public/web_state/page_scroll_state.h', 'public/web_state/page_scroll_state.mm', 'public/web_state/url_verification_constants.h', @@ -119,6 +117,7 @@ 'web_state/blocked_popup_info.h', 'web_state/blocked_popup_info.mm', 'web_state/crw_recurring_task_delegate.h', + 'web_state/js/crw_js_early_script_manager.h', 'web_state/js/crw_js_early_script_manager.mm', 'web_state/js/crw_js_injection_manager.mm', 'web_state/js/crw_js_injection_receiver.mm',
diff --git a/ios/web/public/web_state/js/crw_js_message_manager.h b/ios/web/public/web_state/js/crw_js_message_manager.h deleted file mode 100644 index 85fe836..0000000 --- a/ios/web/public/web_state/js/crw_js_message_manager.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_WEB_PUBLIC_WEB_STATE_JS_CRW_JS_MESSAGE_MANAGER_H_ -#define IOS_WEB_PUBLIC_WEB_STATE_JS_CRW_JS_MESSAGE_MANAGER_H_ - -#import "ios/web/public/web_state/js/crw_js_injection_manager.h" - -// Loads the JavaScript file message.js which contains methods allowing other -// scripts to message the main application. -@interface CRWJSMessageManager : CRWJSInjectionManager -@end - -#endif // IOS_WEB_PUBLIC_WEB_STATE_JS_CRW_JS_MESSAGE_MANAGER_H_
diff --git a/ios/web/public/web_state/js/crw_js_early_script_manager.h b/ios/web/web_state/js/crw_js_early_script_manager.h similarity index 66% rename from ios/web/public/web_state/js/crw_js_early_script_manager.h rename to ios/web/web_state/js/crw_js_early_script_manager.h index 8aa95cd..3371aff 100644 --- a/ios/web/public/web_state/js/crw_js_early_script_manager.h +++ b/ios/web/web_state/js/crw_js_early_script_manager.h
@@ -2,17 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_WEB_PUBLIC_WEB_STATE_JS_CRW_JS_EARLY_SCRIPT_MANAGER_H_ -#define IOS_WEB_PUBLIC_WEB_STATE_JS_CRW_JS_EARLY_SCRIPT_MANAGER_H_ +#ifndef IOS_WEB_WEB_STATE_JS_CRW_JS_EARLY_SCRIPT_MANAGER_H_ +#define IOS_WEB_WEB_STATE_JS_CRW_JS_EARLY_SCRIPT_MANAGER_H_ #import "ios/web/public/web_state/js/crw_js_injection_manager.h" -// TODO(eugenebut): remove this class from web's public interface. - // Manager to handle all the scripts that need to be injected before the page // scripts take effect. Includes the base scripts and any feature scripts // that might need to perform global actions such as overriding HTML methods. @interface CRWJSEarlyScriptManager : CRWJSInjectionManager @end -#endif // IOS_WEB_PUBLIC_WEB_STATE_JS_CRW_JS_EARLY_SCRIPT_MANAGER_H_ +#endif // IOS_WEB_WEB_STATE_JS_CRW_JS_EARLY_SCRIPT_MANAGER_H_
diff --git a/ios/web/web_state/js/crw_js_early_script_manager.mm b/ios/web/web_state/js/crw_js_early_script_manager.mm index 4ce5e11..655c52f 100644 --- a/ios/web/web_state/js/crw_js_early_script_manager.mm +++ b/ios/web/web_state/js/crw_js_early_script_manager.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/web/public/web_state/js/crw_js_early_script_manager.h" +#import "ios/web/web_state/js/crw_js_early_script_manager.h" #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" #import "ios/web/web_state/js/page_script_util.h"
diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc index f338c6f..4689e5f6 100644 --- a/ipc/mojo/ipc_channel_mojo.cc +++ b/ipc/mojo/ipc_channel_mojo.cc
@@ -28,20 +28,26 @@ class MojoChannelFactory : public ChannelFactory { public: MojoChannelFactory(ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, ChannelHandle channel_handle, Channel::Mode mode) - : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {} + : delegate_(delegate), + io_runner_(io_runner), + channel_handle_(channel_handle), + mode_(mode) {} std::string GetName() const override { return channel_handle_.name; } scoped_ptr<Channel> BuildChannel(Listener* listener) override { - return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener); + return ChannelMojo::Create(delegate_, io_runner_, channel_handle_, mode_, + listener); } private: ChannelMojo::Delegate* delegate_; + scoped_refptr<base::TaskRunner> io_runner_; ChannelHandle channel_handle_; Channel::Mode mode_; }; @@ -53,6 +59,7 @@ public mojo::ErrorHandler { public: ClientChannelMojo(ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& handle, Listener* listener); ~ClientChannelMojo() override; @@ -73,9 +80,10 @@ }; ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& handle, Listener* listener) - : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener), + : ChannelMojo(delegate, io_runner, handle, Channel::MODE_CLIENT, listener), binding_(this) { } @@ -104,6 +112,7 @@ class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler { public: ServerChannelMojo(ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& handle, Listener* listener); ~ServerChannelMojo() override; @@ -126,9 +135,10 @@ }; ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& handle, Listener* listener) - : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) { + : ChannelMojo(delegate, io_runner, handle, Channel::MODE_SERVER, listener) { } ServerChannelMojo::~ServerChannelMojo() { @@ -196,17 +206,19 @@ } // static -scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate, - const ChannelHandle& channel_handle, - Mode mode, - Listener* listener) { +scoped_ptr<ChannelMojo> ChannelMojo::Create( + ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, + const ChannelHandle& channel_handle, + Mode mode, + Listener* listener) { switch (mode) { case Channel::MODE_CLIENT: return make_scoped_ptr( - new ClientChannelMojo(delegate, channel_handle, listener)); + new ClientChannelMojo(delegate, io_runner, channel_handle, listener)); case Channel::MODE_SERVER: return make_scoped_ptr( - new ServerChannelMojo(delegate, channel_handle, listener)); + new ServerChannelMojo(delegate, io_runner, channel_handle, listener)); default: NOTREACHED(); return nullptr; @@ -216,20 +228,23 @@ // static scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory( ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& channel_handle) { - return make_scoped_ptr( - new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER)); + return make_scoped_ptr(new MojoChannelFactory( + delegate, io_runner, channel_handle, Channel::MODE_SERVER)); } // static scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory( ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& channel_handle) { - return make_scoped_ptr( - new MojoChannelFactory(delegate, channel_handle, Channel::MODE_CLIENT)); + return make_scoped_ptr(new MojoChannelFactory( + delegate, io_runner, channel_handle, Channel::MODE_CLIENT)); } ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& handle, Mode mode, Listener* listener) @@ -240,16 +255,12 @@ // Create MojoBootstrap after all members are set as it touches // ChannelMojo from a different thread. bootstrap_ = MojoBootstrap::Create(handle, mode, this); - if (delegate) { - if (delegate->GetIOTaskRunner() == - base::MessageLoop::current()->message_loop_proxy()) { - InitDelegate(delegate); - } else { - delegate->GetIOTaskRunner()->PostTask( - FROM_HERE, - base::Bind( - &ChannelMojo::InitDelegate, base::Unretained(this), delegate)); - } + if (io_runner == base::MessageLoop::current()->message_loop_proxy()) { + InitOnIOThread(delegate); + } else { + io_runner->PostTask(FROM_HERE, + base::Bind(&ChannelMojo::InitOnIOThread, + base::Unretained(this), delegate)); } } @@ -257,9 +268,11 @@ Close(); } -void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) { +void ChannelMojo::InitOnIOThread(ChannelMojo::Delegate* delegate) { ipc_support_.reset( new ScopedIPCSupport(base::MessageLoop::current()->task_runner())); + if (!delegate) + return; delegate_ = delegate->ToWeakPtr(); delegate_->OnChannelCreated(weak_factory_.GetWeakPtr()); }
diff --git a/ipc/mojo/ipc_channel_mojo.h b/ipc/mojo/ipc_channel_mojo.h index 1959e0f..40bc256 100644 --- a/ipc/mojo/ipc_channel_mojo.h +++ b/ipc/mojo/ipc_channel_mojo.h
@@ -54,7 +54,6 @@ public: virtual ~Delegate() {} virtual base::WeakPtr<Delegate> ToWeakPtr() = 0; - virtual scoped_refptr<base::TaskRunner> GetIOTaskRunner() = 0; virtual void OnChannelCreated(base::WeakPtr<ChannelMojo> channel) = 0; }; @@ -63,20 +62,24 @@ // Create ChannelMojo. A bootstrap channel is created as well. // |host| must not be null for server channels. - static scoped_ptr<ChannelMojo> Create(Delegate* delegate, - const ChannelHandle& channel_handle, - Mode mode, - Listener* listener); + static scoped_ptr<ChannelMojo> Create( + Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, + const ChannelHandle& channel_handle, + Mode mode, + Listener* listener); // Create a factory object for ChannelMojo. // The factory is used to create Mojo-based ChannelProxy family. // |host| must not be null. static scoped_ptr<ChannelFactory> CreateServerFactory( Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& channel_handle); static scoped_ptr<ChannelFactory> CreateClientFactory( Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& channel_handle); ~ChannelMojo() override; @@ -115,6 +118,7 @@ protected: ChannelMojo(Delegate* delegate, + scoped_refptr<base::TaskRunner> io_runner, const ChannelHandle& channel_handle, Mode mode, Listener* listener); @@ -136,7 +140,7 @@ // notifications invoked by them. typedef internal::MessagePipeReader::DelayedDeleter ReaderDeleter; - void InitDelegate(ChannelMojo::Delegate* delegate); + void InitOnIOThread(ChannelMojo::Delegate* delegate); scoped_ptr<MojoBootstrap> bootstrap_; base::WeakPtr<Delegate> delegate_;
diff --git a/ipc/mojo/ipc_channel_mojo_host.cc b/ipc/mojo/ipc_channel_mojo_host.cc index 7e1bff9..28067cf 100644 --- a/ipc/mojo/ipc_channel_mojo_host.cc +++ b/ipc/mojo/ipc_channel_mojo_host.cc
@@ -30,7 +30,6 @@ // ChannelMojo::Delegate base::WeakPtr<Delegate> ToWeakPtr() override; void OnChannelCreated(base::WeakPtr<ChannelMojo> channel) override; - scoped_refptr<base::TaskRunner> GetIOTaskRunner() override; // Returns an weak ptr of ChannelDelegate instead of Delegate base::WeakPtr<ChannelDelegate> GetWeakPtr(); @@ -73,11 +72,6 @@ channel_ = channel; } -scoped_refptr<base::TaskRunner> -ChannelMojoHost::ChannelDelegate::GetIOTaskRunner() { - return io_task_runner_; -} - void ChannelMojoHost::ChannelDelegate::OnClientLaunched( base::ProcessHandle process) { if (channel_)
diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc index 356d3b3..bf70b7f 100644 --- a/ipc/mojo/ipc_channel_mojo_unittest.cc +++ b/ipc/mojo/ipc_channel_mojo_unittest.cc
@@ -66,12 +66,9 @@ class ChannelClient { public: explicit ChannelClient(IPC::Listener* listener, const char* name) { - ipc_support_.reset( - new IPC::ScopedIPCSupport(main_message_loop_.task_runner())); - channel_ = IPC::ChannelMojo::Create(NULL, + channel_ = IPC::ChannelMojo::Create(NULL, main_message_loop_.task_runner(), IPCTestBase::GetChannelName(name), - IPC::Channel::MODE_CLIENT, - listener); + IPC::Channel::MODE_CLIENT, listener); } void Connect() { @@ -90,7 +87,6 @@ private: base::MessageLoopForIO main_message_loop_; - scoped_ptr<IPC::ScopedIPCSupport> ipc_support_; scoped_ptr<IPC::ChannelMojo> channel_; }; @@ -98,22 +94,17 @@ public: void InitWithMojo(const std::string& test_client_name) { Init(test_client_name); - ipc_support_.reset(new IPC::ScopedIPCSupport(task_runner())); } void TearDown() override { // Make sure Mojo IPC support is properly shutdown on the I/O loop before // TearDown continues. - ipc_support_.reset(); base::RunLoop run_loop; task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure()); run_loop.Run(); IPCTestBase::TearDown(); } - - private: - scoped_ptr<IPC::ScopedIPCSupport> ipc_support_; }; class IPCChannelMojoTest : public IPCChannelMojoTestBase { @@ -123,7 +114,7 @@ base::SequencedTaskRunner* runner) override { host_.reset(new IPC::ChannelMojoHost(task_runner())); return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(), - handle); + task_runner(), handle); } bool DidStartClient() override { @@ -231,7 +222,7 @@ base::SequencedTaskRunner* runner) override { host_.reset(new IPC::ChannelMojoHost(task_runner())); return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(), - handle); + task_runner(), handle); } bool DidStartClient() override { @@ -565,7 +556,7 @@ base::SequencedTaskRunner* runner) override { host_.reset(new IPC::ChannelMojoHost(task_runner())); return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(), - handle); + task_runner(), handle); } virtual bool DidStartClient() override {
diff --git a/ipc/mojo/ipc_mojo_perftest.cc b/ipc/mojo/ipc_mojo_perftest.cc index 9f063ab..dc96dd1 100644 --- a/ipc/mojo/ipc_mojo_perftest.cc +++ b/ipc/mojo/ipc_mojo_perftest.cc
@@ -31,17 +31,15 @@ MojoChannelPerfTest(); void TearDown() override { - ipc_support_.reset(); IPC::test::IPCChannelPerfTestBase::TearDown(); } scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( const IPC::ChannelHandle& handle, base::SequencedTaskRunner* runner) override { - ipc_support_.reset(new IPC::ScopedIPCSupport(runner)); host_.reset(new IPC::ChannelMojoHost(runner)); return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(), - handle); + runner, handle); } bool DidStartClient() override { @@ -52,7 +50,6 @@ } private: - scoped_ptr<IPC::ScopedIPCSupport> ipc_support_; scoped_ptr<IPC::ChannelMojoHost> host_; }; @@ -82,9 +79,6 @@ MojoTestClient(); scoped_ptr<IPC::Channel> CreateChannel(IPC::Listener* listener) override; - - private: - scoped_ptr<IPC::ScopedIPCSupport> ipc_support_; }; MojoTestClient::MojoTestClient() { @@ -93,12 +87,9 @@ scoped_ptr<IPC::Channel> MojoTestClient::CreateChannel( IPC::Listener* listener) { - ipc_support_.reset(new IPC::ScopedIPCSupport(task_runner())); - return scoped_ptr<IPC::Channel>( - IPC::ChannelMojo::Create(NULL, - IPCTestBase::GetChannelName("PerformanceClient"), - IPC::Channel::MODE_CLIENT, - listener)); + return scoped_ptr<IPC::Channel>(IPC::ChannelMojo::Create( + NULL, task_runner(), IPCTestBase::GetChannelName("PerformanceClient"), + IPC::Channel::MODE_CLIENT, listener)); } MULTIPROCESS_IPC_TEST_CLIENT_MAIN(PerformanceClient) {
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc index f7b31a3..53b8a8d 100644 --- a/media/audio/win/audio_low_latency_output_win.cc +++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -135,6 +135,11 @@ DCHECK(!audio_client_.get()); DCHECK(!audio_render_client_.get()); + // Don't allow WASAPI streams to be created for remote output devices, this + // frequently leads to hangs of the audio thread. http://crbug.com/422522. + if (CoreAudioUtil::IsRemoteOutputDevice(device_id_)) + return false; + // Will be set to true if we ended up opening the default communications // device. bool communications_device = false;
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index b56d6e6a..b3bc62fb 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc
@@ -136,18 +136,6 @@ return (LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) != NULL); } -static bool CanCreateDeviceEnumerator() { - ScopedComPtr<IMMDeviceEnumerator> device_enumerator; - HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), - NULL, CLSCTX_INPROC_SERVER); - - // If we hit CO_E_NOTINITIALIZED, CoInitialize has not been called and it - // must be called at least once for each thread that uses the COM library. - CHECK_NE(hr, CO_E_NOTINITIALIZED); - - return SUCCEEDED(hr); -} - static std::string GetDeviceID(IMMDevice* device) { ScopedCoMem<WCHAR> device_id_com; std::string device_id; @@ -156,7 +144,68 @@ return device_id; } -bool CoreAudioUtil::IsSupported() { +static HRESULT GetDeviceFriendlyNameInternal(IMMDevice* device, + std::string* friendly_name) { + // Retrieve user-friendly name of endpoint device. + // Example: "Microphone (Realtek High Definition Audio)". + ScopedComPtr<IPropertyStore> properties; + HRESULT hr = device->OpenPropertyStore(STGM_READ, properties.Receive()); + if (FAILED(hr)) + return hr; + + base::win::ScopedPropVariant friendly_name_pv; + hr = properties->GetValue(PKEY_Device_FriendlyName, + friendly_name_pv.Receive()); + if (FAILED(hr)) + return hr; + + if (friendly_name_pv.get().vt == VT_LPWSTR && + friendly_name_pv.get().pwszVal) { + base::WideToUTF8(friendly_name_pv.get().pwszVal, + wcslen(friendly_name_pv.get().pwszVal), friendly_name); + } + + return hr; +} + +static ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumeratorInternal() { + ScopedComPtr<IMMDeviceEnumerator> device_enumerator; + HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), + NULL, CLSCTX_INPROC_SERVER); + if (hr == CO_E_NOTINITIALIZED) { + LOG(ERROR) << "CoCreateInstance fails with CO_E_NOTINITIALIZED"; + // We have seen crashes which indicates that this method can in fact + // fail with CO_E_NOTINITIALIZED in combination with certain 3rd party + // modules. Calling CoInitializeEx is an attempt to resolve the reported + // issues. See http://crbug.com/378465 for details. + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (SUCCEEDED(hr)) { + hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), + NULL, CLSCTX_INPROC_SERVER); + } + } + return device_enumerator; +} + +static bool IsRemoteSession() { + return !!GetSystemMetrics(SM_REMOTESESSION); +} + +static bool IsRemoteDeviceInternal(IMMDevice* device) { + DCHECK(IsRemoteSession()); + + std::string device_name; + HRESULT hr = GetDeviceFriendlyNameInternal(device, &device_name); + + // This method should only be called if IsRemoteSession() is true, so assume + // we have a remote audio device if we can't tell. + if (FAILED(hr)) + return true; + + return device_name == "Remote Audio"; +} + +static bool IsSupportedInternal() { // It is possible to force usage of WaveXxx APIs by using a command line flag. const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); if (cmd_line->HasSwitch(switches::kForceWaveAudio)) { @@ -176,19 +225,47 @@ // the Audioses DLL since it depends on Mmdevapi.dll. // See http://crbug.com/166397 why this extra step is required to guarantee // Core Audio support. - static bool g_audioses_dll_available = LoadAudiosesDll(); - if (!g_audioses_dll_available) + if (!LoadAudiosesDll()) return false; // Being able to load the Audioses.dll does not seem to be sufficient for // all devices to guarantee Core Audio support. To be 100%, we also verify // that it is possible to a create the IMMDeviceEnumerator interface. If this // works as well we should be home free. - static bool g_can_create_device_enumerator = CanCreateDeviceEnumerator(); - LOG_IF(ERROR, !g_can_create_device_enumerator) - << "Failed to create Core Audio device enumerator on thread with ID " - << GetCurrentThreadId(); - return g_can_create_device_enumerator; + ScopedComPtr<IMMDeviceEnumerator> device_enumerator = + CreateDeviceEnumeratorInternal(); + if (!device_enumerator) { + LOG(ERROR) + << "Failed to create Core Audio device enumerator on thread with ID " + << GetCurrentThreadId(); + return false; + } + + // Don't use CoreAudio when a remote desktop session with remote audio is + // present; several users report only WaveAudio working for them and crash + // reports show hangs when calling into the OS for CoreAudio API calls. See + // http://crbug.com/422522 and http://crbug.com/180591. + // + // Note: There's another check in WASAPIAudioOutputStream::Open() for the case + // where a remote session is created after Chrome has been started. Graceful + // fallback to WaveOut will occur in this case via AudioOutputResampler. + if (!IsRemoteSession()) + return true; + + ScopedComPtr<IMMDevice> device; + HRESULT hr = device_enumerator->GetDefaultAudioEndpoint(eRender, eConsole, + device.Receive()); + + // Assume remote audio playback if we can't tell. + if (FAILED(hr)) + return false; + + return !IsRemoteDeviceInternal(device.get()); +} + +bool CoreAudioUtil::IsSupported() { + static bool g_is_supported = IsSupportedInternal(); + return g_is_supported; } base::TimeDelta CoreAudioUtil::RefererenceTimeToTimeDelta(REFERENCE_TIME time) { @@ -233,22 +310,9 @@ ScopedComPtr<IMMDeviceEnumerator> CoreAudioUtil::CreateDeviceEnumerator() { DCHECK(IsSupported()); - ScopedComPtr<IMMDeviceEnumerator> device_enumerator; - HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), - NULL, CLSCTX_INPROC_SERVER); - if (hr == CO_E_NOTINITIALIZED) { - LOG(ERROR) << "CoCreateInstance fails with CO_E_NOTINITIALIZED"; - // We have seen crashes which indicates that this method can in fact - // fail with CO_E_NOTINITIALIZED in combination with certain 3rd party - // modules. Calling CoInitializeEx is an attempt to resolve the reported - // issues. See http://crbug.com/378465 for details. - hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - if (SUCCEEDED(hr)) { - hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), - NULL, CLSCTX_INPROC_SERVER); - } - } - CHECK(SUCCEEDED(hr)); + ScopedComPtr<IMMDeviceEnumerator> device_enumerator = + CreateDeviceEnumeratorInternal(); + CHECK(device_enumerator); return device_enumerator; } @@ -323,21 +387,9 @@ if (device_name.unique_id.empty()) return E_FAIL; - // Retrieve user-friendly name of endpoint device. - // Example: "Microphone (Realtek High Definition Audio)". - ScopedComPtr<IPropertyStore> properties; - HRESULT hr = device->OpenPropertyStore(STGM_READ, properties.Receive()); + HRESULT hr = GetDeviceFriendlyNameInternal(device, &device_name.device_name); if (FAILED(hr)) return hr; - base::win::ScopedPropVariant friendly_name; - hr = properties->GetValue(PKEY_Device_FriendlyName, friendly_name.Receive()); - if (FAILED(hr)) - return hr; - if (friendly_name.get().vt == VT_LPWSTR && friendly_name.get().pwszVal) { - base::WideToUTF8(friendly_name.get().pwszVal, - wcslen(friendly_name.get().pwszVal), - &device_name.device_name); - } *name = device_name; DVLOG(2) << "friendly name: " << device_name.device_name; @@ -854,4 +906,15 @@ AUDCLNT_BUFFERFLAGS_SILENT)); } +bool CoreAudioUtil::IsRemoteOutputDevice(const std::string& device_id) { + DCHECK(IsSupported()); + if (!IsRemoteSession()) + return false; + ScopedComPtr<IMMDevice> device(device_id.empty() + ? CreateDefaultDevice(eRender, eConsole) + : CreateDevice(device_id)); + // Assume remote audio if we can't tell. + return device ? IsRemoteDeviceInternal(device.get()) : true; +} + } // namespace media
diff --git a/media/audio/win/core_audio_util_win.h b/media/audio/win/core_audio_util_win.h index 4e93531..75e90ce0 100644 --- a/media/audio/win/core_audio_util_win.h +++ b/media/audio/win/core_audio_util_win.h
@@ -229,6 +229,9 @@ static bool FillRenderEndpointBufferWithSilence( IAudioClient* client, IAudioRenderClient* render_client); + // Returns true if the given output device is a remote audio endpoint. + static bool IsRemoteOutputDevice(const std::string& device_id); + private: CoreAudioUtil() {} ~CoreAudioUtil() {}
diff --git a/media/base/audio_converter.cc b/media/base/audio_converter.cc index 1941119..be68ac6 100644 --- a/media/base/audio_converter.cc +++ b/media/base/audio_converter.cc
@@ -33,7 +33,8 @@ CHECK(output_params.IsValid()); // Handle different input and output channel layouts. - if (input_params.channel_layout() != output_params.channel_layout()) { + if (input_params.channel_layout() != output_params.channel_layout() || + input_params.channels() != output_params.channels()) { DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout() << " to " << output_params.channel_layout() << "; from " << input_params.channels() << " channels to "
diff --git a/media/base/audio_converter_unittest.cc b/media/base/audio_converter_unittest.cc index b1564db4..dcc3db6 100644 --- a/media/base/audio_converter_unittest.cc +++ b/media/base/audio_converter_unittest.cc
@@ -194,15 +194,17 @@ }; // Ensure the buffer delay provided by AudioConverter is accurate. -TEST(AudioConverterTest, AudioDelay) { +TEST(AudioConverterTest, AudioDelayAndDiscreteChannelCount) { // Choose input and output parameters such that the transform must make // multiple calls to fill the buffer. - AudioParameters input_parameters = AudioParameters( - AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, - kBitsPerChannel, kLowLatencyBufferSize); - AudioParameters output_parameters = AudioParameters( - AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate * 2, - kBitsPerChannel, kHighLatencyBufferSize); + AudioParameters input_parameters(AudioParameters::AUDIO_PCM_LINEAR, + CHANNEL_LAYOUT_DISCRETE, 10, kSampleRate, + kBitsPerChannel, kLowLatencyBufferSize, + AudioParameters::NO_EFFECTS); + AudioParameters output_parameters(AudioParameters::AUDIO_PCM_LINEAR, + CHANNEL_LAYOUT_DISCRETE, 5, kSampleRate * 2, + kBitsPerChannel, kHighLatencyBufferSize, + AudioParameters::NO_EFFECTS); AudioConverter converter(input_parameters, output_parameters, false); FakeAudioRenderCallback callback(0.2); @@ -225,6 +227,7 @@ EXPECT_EQ(expected_last_delay_milliseconds, callback.last_audio_delay_milliseconds()); + EXPECT_EQ(input_parameters.channels(), callback.last_channel_count()); } TEST_P(AudioConverterTest, ArbitraryOutputRequestSize) {
diff --git a/media/base/fake_audio_render_callback.cc b/media/base/fake_audio_render_callback.cc index 5a0979e9e..73d606e 100644 --- a/media/base/fake_audio_render_callback.cc +++ b/media/base/fake_audio_render_callback.cc
@@ -15,6 +15,7 @@ : half_fill_(false), step_(step), last_audio_delay_milliseconds_(-1), + last_channel_count_(-1), volume_(1) { reset(); } @@ -24,6 +25,8 @@ int FakeAudioRenderCallback::Render(AudioBus* audio_bus, int audio_delay_milliseconds) { last_audio_delay_milliseconds_ = audio_delay_milliseconds; + last_channel_count_ = audio_bus->channels(); + int number_of_frames = audio_bus->frames(); if (half_fill_) number_of_frames /= 2;
diff --git a/media/base/fake_audio_render_callback.h b/media/base/fake_audio_render_callback.h index 695365f..7805fc6 100644 --- a/media/base/fake_audio_render_callback.h +++ b/media/base/fake_audio_render_callback.h
@@ -42,16 +42,21 @@ // Returns the last |audio_delay_milliseconds| provided to Render() or -1 if // no Render() call occurred. - int last_audio_delay_milliseconds() { return last_audio_delay_milliseconds_; } + int last_audio_delay_milliseconds() const { + return last_audio_delay_milliseconds_; + } // Set volume information used by ProvideAudioTransformInput(). void set_volume(double volume) { volume_ = volume; } + int last_channel_count() const { return last_channel_count_; } + private: bool half_fill_; double x_; double step_; int last_audio_delay_milliseconds_; + int last_channel_count_; double volume_; DISALLOW_COPY_AND_ASSIGN(FakeAudioRenderCallback);
diff --git a/media/cast/OWNERS b/media/cast/OWNERS index f8e61c3..209c9d3d 100644 --- a/media/cast/OWNERS +++ b/media/cast/OWNERS
@@ -1,5 +1,3 @@ hclam@chromium.org hubbe@chromium.org -mikhal@chromium.org miu@chromium.org -pwestin@google.com
diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc index 670dabdc..ec0de289 100644 --- a/media/cdm/aes_decryptor.cc +++ b/media/cdm/aes_decryptor.cc
@@ -224,12 +224,15 @@ return output; } -AesDecryptor::AesDecryptor(const SessionMessageCB& session_message_cb, +AesDecryptor::AesDecryptor(const GURL& /* security_origin */, + const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, const SessionKeysChangeCB& session_keys_change_cb) : session_message_cb_(session_message_cb), session_closed_cb_(session_closed_cb), session_keys_change_cb_(session_keys_change_cb) { + // AesDecryptor doesn't keep any persistent data, so no need to do anything + // with |security_origin|. DCHECK(!session_message_cb_.is_null()); DCHECK(!session_closed_cb_.is_null()); DCHECK(!session_keys_change_cb_.is_null());
diff --git a/media/cdm/aes_decryptor.h b/media/cdm/aes_decryptor.h index 9a13e62..5c7a06c 100644 --- a/media/cdm/aes_decryptor.h +++ b/media/cdm/aes_decryptor.h
@@ -18,6 +18,8 @@ #include "media/base/media_export.h" #include "media/base/media_keys.h" +class GURL; + namespace crypto { class SymmetricKey; } @@ -30,7 +32,8 @@ public CdmContext, public Decryptor { public: - AesDecryptor(const SessionMessageCB& session_message_cb, + AesDecryptor(const GURL& security_origin, + const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, const SessionKeysChangeCB& session_keys_change_cb); ~AesDecryptor() override;
diff --git a/media/cdm/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc index 2d529abc..3f26239 100644 --- a/media/cdm/aes_decryptor_unittest.cc +++ b/media/cdm/aes_decryptor_unittest.cc
@@ -17,6 +17,7 @@ #include "media/cdm/aes_decryptor.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" using ::testing::_; using ::testing::Gt; @@ -34,8 +35,6 @@ return (root.get() && root->GetType() == base::Value::TYPE_DICTIONARY); } -class GURL; - namespace media { const uint8 kOriginalData[] = "Original subsample data."; @@ -215,7 +214,8 @@ class AesDecryptorTest : public testing::Test { public: AesDecryptorTest() - : decryptor_(base::Bind(&AesDecryptorTest::OnSessionMessage, + : decryptor_(GURL::EmptyGURL(), + base::Bind(&AesDecryptorTest::OnSessionMessage, base::Unretained(this)), base::Bind(&AesDecryptorTest::OnSessionClosed, base::Unretained(this)),
diff --git a/media/cdm/default_cdm_factory.cc b/media/cdm/default_cdm_factory.cc index 9d8ea83..a87760c12 100644 --- a/media/cdm/default_cdm_factory.cc +++ b/media/cdm/default_cdm_factory.cc
@@ -6,6 +6,7 @@ #include "media/base/key_systems.h" #include "media/cdm/aes_decryptor.h" +#include "url/gurl.h" namespace media { @@ -25,9 +26,13 @@ const LegacySessionErrorCB& legacy_session_error_cb, const SessionKeysChangeCB& session_keys_change_cb, const SessionExpirationUpdateCB& session_expiration_update_cb) { + if (!security_origin.is_valid()) + return nullptr; + if (CanUseAesDecryptor(key_system)) { - return make_scoped_ptr(new AesDecryptor( - session_message_cb, session_closed_cb, session_keys_change_cb)); + return make_scoped_ptr(new AesDecryptor(security_origin, session_message_cb, + session_closed_cb, + session_keys_change_cb)); } return nullptr;
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index 2550368..725ee88f 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -23,6 +23,7 @@ #include "media/cdm/json_web_key.h" #include "media/cdm/ppapi/cdm_file_io_test.h" #include "media/cdm/ppapi/external_clear_key/cdm_video_decoder.h" +#include "url/gurl.h" #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) #include "base/basictypes.h" @@ -262,7 +263,8 @@ if (!host) return NULL; - return new media::ClearKeyCdm(host, key_system_string); + // TODO(jrummell): Obtain the proper origin for this instance. + return new media::ClearKeyCdm(host, key_system_string, GURL::EmptyGURL()); } const char* GetCdmVersion() { @@ -271,8 +273,11 @@ namespace media { -ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, const std::string& key_system) +ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, + const std::string& key_system, + const GURL& origin) : decryptor_( + origin, base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), base::Bind(&ClearKeyCdm::OnSessionKeysChange,
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.h b/media/cdm/ppapi/external_clear_key/clear_key_cdm.h index f25a1b0..6418679 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.h +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.h
@@ -22,6 +22,8 @@ #define CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER #endif +class GURL; + namespace media { class FileIOTestRunner; class CdmVideoDecoder; @@ -31,7 +33,7 @@ // Clear key implementation of the cdm::ContentDecryptionModule interface. class ClearKeyCdm : public ClearKeyCdmInterface { public: - ClearKeyCdm(Host* host, const std::string& key_system); + ClearKeyCdm(Host* host, const std::string& key_system, const GURL& origin); ~ClearKeyCdm() override; // ContentDecryptionModule implementation.
diff --git a/media/mojo/services/mojo_cdm_service.cc b/media/mojo/services/mojo_cdm_service.cc index eff147f6..58c335d 100644 --- a/media/mojo/services/mojo_cdm_service.cc +++ b/media/mojo/services/mojo_cdm_service.cc
@@ -12,6 +12,7 @@ #include "media/mojo/services/mojo_cdm_promise.h" #include "mojo/common/common_type_converters.h" #include "mojo/common/url_type_converters.h" +#include "url/gurl.h" namespace media { @@ -23,7 +24,9 @@ base::WeakPtr<MojoCdmService> weak_this = weak_factory_.GetWeakPtr(); if (CanUseAesDecryptor(key_system)) { + // TODO(jrummell): Determine proper origin. cdm_.reset(new AesDecryptor( + GURL::EmptyGURL(), base::Bind(&MojoCdmService::OnSessionMessage, weak_this), base::Bind(&MojoCdmService::OnSessionClosed, weak_this), base::Bind(&MojoCdmService::OnSessionKeysChange, weak_this)));
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn index 60849c1e..e5e5f969 100644 --- a/media/test/BUILD.gn +++ b/media/test/BUILD.gn
@@ -43,6 +43,7 @@ "//media/audio:test_support", "//media/base:test_support", "//testing/gtest", + "//url", # TODO(dalecurtis): Required since the gmock header is included in the # header for pipeline_integration_test_base.h. This should be moved into
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index cea6fdcc..ead238c 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -21,6 +21,7 @@ #include "media/renderers/renderer_impl.h" #include "media/test/pipeline_integration_test_base.h" #include "testing/gmock/include/gmock/gmock.h" +#include "url/gurl.h" #if defined(MOJO_RENDERER) #include "media/mojo/services/mojo_renderer_impl.h" @@ -169,7 +170,8 @@ }; FakeEncryptedMedia(AppBase* app) - : decryptor_(base::Bind(&FakeEncryptedMedia::OnSessionMessage, + : decryptor_(GURL::EmptyGURL(), + base::Bind(&FakeEncryptedMedia::OnSessionMessage, base::Unretained(this)), base::Bind(&FakeEncryptedMedia::OnSessionClosed, base::Unretained(this)),
diff --git a/media/video/capture/fake_video_capture_device.cc b/media/video/capture/fake_video_capture_device.cc index 5e5c387..4f3a8bb 100644 --- a/media/video/capture/fake_video_capture_device.cc +++ b/media/video/capture/fake_video_capture_device.cc
@@ -156,7 +156,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); const scoped_refptr<VideoCaptureDevice::Client::Buffer> capture_buffer = - client_->ReserveOutputBuffer(VideoFrame::I420, + client_->ReserveOutputBuffer(capture_format_.pixel_format, capture_format_.frame_size); DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; if (!capture_buffer)
diff --git a/media/video/capture/fake_video_capture_device_unittest.cc b/media/video/capture/fake_video_capture_device_unittest.cc index 042fa7c..e413c5ed4 100644 --- a/media/video/capture/fake_video_capture_device_unittest.cc +++ b/media/video/capture/fake_video_capture_device_unittest.cc
@@ -75,12 +75,11 @@ } // Virtual methods for capturing using Client's Buffers. - scoped_refptr<Buffer> ReserveOutputBuffer(VideoFrame::Format format, + scoped_refptr<Buffer> ReserveOutputBuffer(media::VideoPixelFormat format, const gfx::Size& dimensions) { - EXPECT_EQ(format, VideoFrame::I420); + EXPECT_EQ(format, PIXEL_FORMAT_I420); EXPECT_GT(dimensions.GetArea(), 0); - return make_scoped_refptr( - new MockBuffer(0, VideoFrame::AllocationSize(format, dimensions))); + return make_scoped_refptr(new MockBuffer(0, dimensions.GetArea() * 3 / 2)); } void OnIncomingCapturedVideoFrame( const scoped_refptr<Buffer>& buffer,
diff --git a/media/video/capture/video_capture_device.h b/media/video/capture/video_capture_device.h index b243b0ed..e5e42f8 100644 --- a/media/video/capture/video_capture_device.h +++ b/media/video/capture/video_capture_device.h
@@ -244,7 +244,7 @@ // The output buffer stays reserved for use until the Buffer object is // destroyed. virtual scoped_refptr<Buffer> ReserveOutputBuffer( - media::VideoFrame::Format format, + media::VideoPixelFormat format, const gfx::Size& dimensions) = 0; // Captured a new video frame, held in |frame|.
diff --git a/media/video/capture/video_capture_device_unittest.cc b/media/video/capture/video_capture_device_unittest.cc index 061e6f0..a01fbab9 100644 --- a/media/video/capture/video_capture_device_unittest.cc +++ b/media/video/capture/video_capture_device_unittest.cc
@@ -65,8 +65,8 @@ class MockClient : public VideoCaptureDevice::Client { public: MOCK_METHOD2(ReserveOutputBuffer, - scoped_refptr<Buffer>(VideoFrame::Format format, - const gfx::Size& dimensions)); + scoped_refptr<Buffer>(media::VideoPixelFormat format, + const gfx::Size& dimensions)); MOCK_METHOD9(OnIncomingCapturedYuvData, void (const uint8* y_data, const uint8* u_data,
diff --git a/mojo/services/html_viewer/blink_resource_constants.h b/mojo/services/html_viewer/blink_resource_constants.h index 6fc4ff1..fd571ba 100644 --- a/mojo/services/html_viewer/blink_resource_constants.h +++ b/mojo/services/html_viewer/blink_resource_constants.h
@@ -16,63 +16,63 @@ }; const DataResource kDataResources[] = { - {"missingImage", IDR2_BROKENIMAGE}, + {"missingImage", IDR_BROKENIMAGE}, // Skipping missingImage@2x - {"mediaplayerPause", IDR2_MEDIAPLAYER_PAUSE_BUTTON}, - {"mediaplayerPauseHover", IDR2_MEDIAPLAYER_PAUSE_BUTTON_HOVER}, - {"mediaplayerPauseDown", IDR2_MEDIAPLAYER_PAUSE_BUTTON_DOWN}, - {"mediaplayerPlay", IDR2_MEDIAPLAYER_PLAY_BUTTON}, - {"mediaplayerPlayHover", IDR2_MEDIAPLAYER_PLAY_BUTTON_HOVER}, - {"mediaplayerPlayDown", IDR2_MEDIAPLAYER_PLAY_BUTTON_DOWN}, - {"mediaplayerPlayDisabled", IDR2_MEDIAPLAYER_PLAY_BUTTON_DISABLED}, - {"mediaplayerSoundLevel3", IDR2_MEDIAPLAYER_SOUND_LEVEL3_BUTTON}, - {"mediaplayerSoundLevel3Hover", IDR2_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER}, - {"mediaplayerSoundLevel3Down", IDR2_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN}, - {"mediaplayerSoundLevel2", IDR2_MEDIAPLAYER_SOUND_LEVEL2_BUTTON}, - {"mediaplayerSoundLevel2Hover", IDR2_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER}, - {"mediaplayerSoundLevel2Down", IDR2_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN}, - {"mediaplayerSoundLevel1", IDR2_MEDIAPLAYER_SOUND_LEVEL1_BUTTON}, - {"mediaplayerSoundLevel1Hover", IDR2_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER}, - {"mediaplayerSoundLevel1Down", IDR2_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN}, - {"mediaplayerSoundLevel0", IDR2_MEDIAPLAYER_SOUND_LEVEL0_BUTTON}, - {"mediaplayerSoundLevel0Hover", IDR2_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER}, - {"mediaplayerSoundLevel0Down", IDR2_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN}, - {"mediaplayerSoundDisabled", IDR2_MEDIAPLAYER_SOUND_DISABLED}, - {"mediaplayerSliderThumb", IDR2_MEDIAPLAYER_SLIDER_THUMB}, - {"mediaplayerSliderThumbHover", IDR2_MEDIAPLAYER_SLIDER_THUMB_HOVER}, - {"mediaplayerSliderThumbDown", IDR2_MEDIAPLAYER_SLIDER_THUMB_DOWN}, - {"mediaplayerVolumeSliderThumb", IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB}, + {"mediaplayerPause", IDR_MEDIAPLAYER_PAUSE_BUTTON}, + {"mediaplayerPauseHover", IDR_MEDIAPLAYER_PAUSE_BUTTON_HOVER}, + {"mediaplayerPauseDown", IDR_MEDIAPLAYER_PAUSE_BUTTON_DOWN}, + {"mediaplayerPlay", IDR_MEDIAPLAYER_PLAY_BUTTON}, + {"mediaplayerPlayHover", IDR_MEDIAPLAYER_PLAY_BUTTON_HOVER}, + {"mediaplayerPlayDown", IDR_MEDIAPLAYER_PLAY_BUTTON_DOWN}, + {"mediaplayerPlayDisabled", IDR_MEDIAPLAYER_PLAY_BUTTON_DISABLED}, + {"mediaplayerSoundLevel3", IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON}, + {"mediaplayerSoundLevel3Hover", IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER}, + {"mediaplayerSoundLevel3Down", IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN}, + {"mediaplayerSoundLevel2", IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON}, + {"mediaplayerSoundLevel2Hover", IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER}, + {"mediaplayerSoundLevel2Down", IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN}, + {"mediaplayerSoundLevel1", IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON}, + {"mediaplayerSoundLevel1Hover", IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER}, + {"mediaplayerSoundLevel1Down", IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN}, + {"mediaplayerSoundLevel0", IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON}, + {"mediaplayerSoundLevel0Hover", IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER}, + {"mediaplayerSoundLevel0Down", IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN}, + {"mediaplayerSoundDisabled", IDR_MEDIAPLAYER_SOUND_DISABLED}, + {"mediaplayerSliderThumb", IDR_MEDIAPLAYER_SLIDER_THUMB}, + {"mediaplayerSliderThumbHover", IDR_MEDIAPLAYER_SLIDER_THUMB_HOVER}, + {"mediaplayerSliderThumbDown", IDR_MEDIAPLAYER_SLIDER_THUMB_DOWN}, + {"mediaplayerVolumeSliderThumb", IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB}, {"mediaplayerVolumeSliderThumbHover", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER}, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER}, {"mediaplayerVolumeSliderThumbDown", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN}, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN}, {"mediaplayerVolumeSliderThumbDisabled", - IDR2_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED}, - {"mediaplayerClosedCaption", IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON}, + IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED}, + {"mediaplayerClosedCaption", IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON}, {"mediaplayerClosedCaptionHover", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER}, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER}, {"mediaplayerClosedCaptionDown", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN}, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN}, {"mediaplayerClosedCaptionDisabled", - IDR2_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED}, - {"mediaplayerFullscreen", IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON}, - {"mediaplayerFullscreenHover", IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER}, - {"mediaplayerFullscreenDown", IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN}, - {"mediaplayerCastOff", IDR2_MEDIAPLAYER_CAST_BUTTON_OFF}, - {"mediaplayerCastOn", IDR2_MEDIAPLAYER_CAST_BUTTON_ON}, + IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED}, + {"mediaplayerFullscreen", IDR_MEDIAPLAYER_FULLSCREEN_BUTTON}, + {"mediaplayerFullscreenHover", IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER}, + {"mediaplayerFullscreenDown", IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN}, + {"mediaplayerCastOff", IDR_MEDIAPLAYER_CAST_BUTTON_OFF}, + {"mediaplayerCastOn", IDR_MEDIAPLAYER_CAST_BUTTON_ON}, {"mediaplayerFullscreenDisabled", - IDR2_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED}, - {"mediaplayerOverlayCastOff", IDR2_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF}, - {"mediaplayerOverlayPlay", IDR2_MEDIAPLAYER_OVERLAY_PLAY_BUTTON}, - {"panIcon", IDR2_PAN_SCROLL_ICON}, - {"searchCancel", IDR2_SEARCH_CANCEL}, - {"searchCancelPressed", IDR2_SEARCH_CANCEL_PRESSED}, - {"searchMagnifier", IDR2_SEARCH_MAGNIFIER}, - {"searchMagnifierResults", IDR2_SEARCH_MAGNIFIER_RESULTS}, - {"textAreaResizeCorner", IDR2_TEXTAREA_RESIZER}, + IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED}, + {"mediaplayerOverlayCastOff", IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF}, + {"mediaplayerOverlayPlay", IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON}, + {"panIcon", IDR_PAN_SCROLL_ICON}, + {"searchCancel", IDR_SEARCH_CANCEL}, + {"searchCancelPressed", IDR_SEARCH_CANCEL_PRESSED}, + {"searchMagnifier", IDR_SEARCH_MAGNIFIER}, + {"searchMagnifierResults", IDR_SEARCH_MAGNIFIER_RESULTS}, + {"textAreaResizeCorner", IDR_TEXTAREA_RESIZER}, // Skipping "textAreaResizeCorner@2x" - {"generatePassword", IDR2_PASSWORD_GENERATION_ICON}, - {"generatePasswordHover", IDR2_PASSWORD_GENERATION_ICON_HOVER}, + {"generatePassword", IDR_PASSWORD_GENERATION_ICON}, + {"generatePasswordHover", IDR_PASSWORD_GENERATION_ICON_HOVER}, {"html.css", IDR_UASTYLE_HTML_CSS}, {"quirks.css", IDR_UASTYLE_QUIRKS_CSS}, {"view-source.css", IDR_UASTYLE_VIEW_SOURCE_CSS},
diff --git a/native_client_sdk/doc_generated/reference/nacl-manifest-format.html b/native_client_sdk/doc_generated/reference/nacl-manifest-format.html index b796f0c..69de516f 100644 --- a/native_client_sdk/doc_generated/reference/nacl-manifest-format.html +++ b/native_client_sdk/doc_generated/reference/nacl-manifest-format.html
@@ -77,7 +77,7 @@ } } </pre> -<p>Portable Native Client applications can also specify an <code>optlevel</code> field. +<p id="pnacl-nmf-optlevels">Portable Native Client applications can also specify an <code>optlevel</code> field. The <code>optlevel</code> field is an optimization level <em>hint</em>, which is a number (zero and higher). Higher numbers indicate more optimization effort. Setting a higher optimization level will improve the application’s
diff --git a/native_client_sdk/doc_generated/sdk/release-notes.html b/native_client_sdk/doc_generated/sdk/release-notes.html index 58762a8..a96ec9f1 100644 --- a/native_client_sdk/doc_generated/sdk/release-notes.html +++ b/native_client_sdk/doc_generated/sdk/release-notes.html
@@ -25,6 +25,16 @@ deprecated and will be removed in the next release. PNaCl has used libc++ (which is much more up-to-date, currently based on LLVM 3.6) as the default since Pepper 33.</li> +<li>PNaCl’s experimental <a class="reference external" href="https://chromium.googlesource.com/native_client/pnacl-subzero/+/master/README.rst">Subzero translator</a> is available for x86-32 NaCl in +Chrome version 43, behind a flag. To give it a try, run Chrome with the +<code>--enable-pnacl-subzero</code> commandline flag, and use the <code>optlevel 0</code> +<a class="reference internal" href="/native-client/reference/nacl-manifest-format.html#pnacl-nmf-optlevels"><em>NaCl manifest option</em></a>. Application startup time +should be several times faster than the previous LLVM-based <code>optlevel 0</code> +mode, with similar code quality. Note that x86-32 NaCl requires a 32-bit +Chrome. On Windows, it also requires a 32-bit Windows OS, but 64-bit Linux +OSes can run x86-32 NaCl. If you try it out, please send us feedback +on <a class="reference external" href="https://groups.google.com/forum/#!forum/native-client-dev">native-client-dev</a>. We are working on improvements and adding +new targets.</li> </ul> <h3 id="pepper">Pepper</h3> <ul class="small-gap">
diff --git a/native_client_sdk/src/build_tools/test_projects.py b/native_client_sdk/src/build_tools/test_projects.py index d2ea2d1..2fe0bfc 100755 --- a/native_client_sdk/src/build_tools/test_projects.py +++ b/native_client_sdk/src/build_tools/test_projects.py
@@ -74,6 +74,9 @@ {'name': 'graphics_3d', 'platform': ('win', 'linux', 'mac')}, {'name': 'video_decode', 'platform': ('win', 'linux', 'mac')}, {'name': 'video_encode', 'platform': ('win', 'linux', 'mac')}, + # TODO(sbc): Disable pi_generator on linux/win/mac. See + # http://crbug.com/475255. + {'name': 'pi_generator', 'platform': ('win', 'linux', 'mac')}, # media_stream_audio uses audio input devices which are not supported. {'name': 'media_stream_audio', 'platform': ('win', 'linux', 'mac')}, # media_stream_video uses 3D and webcam which are not supported.
diff --git a/native_client_sdk/src/doc/reference/nacl-manifest-format.rst b/native_client_sdk/src/doc/reference/nacl-manifest-format.rst index a8579987..2df2de1d 100644 --- a/native_client_sdk/src/doc/reference/nacl-manifest-format.rst +++ b/native_client_sdk/src/doc/reference/nacl-manifest-format.rst
@@ -77,6 +77,8 @@ } } +.. _pnacl_nmf_optlevels: + Portable Native Client applications can also specify an ``optlevel`` field. The ``optlevel`` field is an optimization level *hint*, which is a number (zero and higher). Higher numbers indicate more optimization effort.
diff --git a/native_client_sdk/src/doc/sdk/release-notes.rst b/native_client_sdk/src/doc/sdk/release-notes.rst index 3c85e14..4ec487e 100644 --- a/native_client_sdk/src/doc/sdk/release-notes.rst +++ b/native_client_sdk/src/doc/sdk/release-notes.rst
@@ -33,8 +33,20 @@ deprecated and will be removed in the next release. PNaCl has used libc++ (which is much more up-to-date, currently based on LLVM 3.6) as the default since Pepper 33. +* PNaCl's experimental `Subzero translator`_ is available for x86-32 NaCl in + Chrome version 43, behind a flag. To give it a try, run Chrome with the + ``--enable-pnacl-subzero`` commandline flag, and use the ``optlevel 0`` + :ref:`NaCl manifest option<pnacl_nmf_optlevels>`. Application startup time + should be several times faster than the previous LLVM-based ``optlevel 0`` + mode, with similar code quality. Note that x86-32 NaCl requires a 32-bit + Chrome. On Windows, it also requires a 32-bit Windows OS, but 64-bit Linux + OSes can run x86-32 NaCl. If you try it out, please send us feedback + on `native-client-dev`_. We are working on improvements and adding + new targets. .. _`code generation bug on ARM`: https://code.google.com/p/chromium/issues/detail?id=460432 +.. _`Subzero translator`: https://chromium.googlesource.com/native_client/pnacl-subzero/+/master/README.rst +.. _`native-client-dev`: https://groups.google.com/forum/#!forum/native-client-dev Pepper ------
diff --git a/net/BUILD.gn b/net/BUILD.gn index eaf01d2..05f1106d 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -197,8 +197,8 @@ "cert/test_root_certs_nss.cc", "cert/x509_util_nss.cc", "cert/x509_util_nss.h", - "ocsp/nss_ocsp.cc", - "ocsp/nss_ocsp.h", + "cert_net/nss_ocsp.cc", + "cert_net/nss_ocsp.h", "quic/crypto/aead_base_decrypter_nss.cc", "quic/crypto/aead_base_encrypter_nss.cc", "quic/crypto/aes_128_gcm_12_decrypter_nss.cc", @@ -271,11 +271,11 @@ "socket/ssl_client_socket_openssl.h", "socket/ssl_server_socket_openssl.cc", "socket/ssl_server_socket_openssl.h", - "socket/ssl_session_cache_openssl.cc", - "socket/ssl_session_cache_openssl.h", "ssl/openssl_platform_key.h", "ssl/openssl_ssl_util.cc", "ssl/openssl_ssl_util.h", + "ssl/ssl_client_session_cache_openssl.cc", + "ssl/ssl_client_session_cache_openssl.h", ] if (is_mac) { sources -= [ "ssl/openssl_platform_key_mac.cc" ] @@ -342,8 +342,8 @@ # keep them in that case. sources -= [ "cert/test_root_certs_nss.cc", - "ocsp/nss_ocsp.cc", - "ocsp/nss_ocsp.h", + "cert_net/nss_ocsp.cc", + "cert_net/nss_ocsp.h", ] } } @@ -474,8 +474,8 @@ "cert/test_root_certs_nss.cc", "cert/x509_util_nss.cc", "cert/x509_util_nss.h", - "ocsp/nss_ocsp.cc", - "ocsp/nss_ocsp.h", + "cert_net/nss_ocsp.cc", + "cert_net/nss_ocsp.h", "proxy/proxy_resolver_mac.cc", "proxy/proxy_server_mac.cc", ] @@ -1409,7 +1409,7 @@ "cert/x509_util_openssl_unittest.cc", "quic/test_tools/crypto_test_utils_openssl.cc", "socket/ssl_client_socket_openssl_unittest.cc", - "socket/ssl_session_cache_openssl_unittest.cc", + "ssl/ssl_client_session_cache_openssl_unittest.cc", ] if (!is_desktop_linux && !is_chromeos) { sources -= [ "cert/nss_cert_database_unittest.cc" ] @@ -1430,7 +1430,7 @@ if (use_openssl || (!is_desktop_linux && !is_chromeos && !is_ios)) { # Only include this test when on Posix and using NSS for # cert verification or on iOS (which also uses NSS for certs). - sources -= [ "ocsp/nss_ocsp_unittest.cc" ] + sources -= [ "cert_net/nss_ocsp_unittest.cc" ] } if (!use_openssl_certs) { @@ -1564,6 +1564,7 @@ "spdy/fuzzing/hpack_fuzz_util_test.cc", # Need TestServer. + "cert_net/cert_net_fetcher_impl_unittest.cc", "proxy/proxy_script_fetcher_impl_unittest.cc", "socket/ssl_client_socket_unittest.cc", "url_request/url_fetcher_impl_unittest.cc",
diff --git a/net/base/sdch_dictionary.cc b/net/base/sdch_dictionary.cc new file mode 100644 index 0000000..875cce6 --- /dev/null +++ b/net/base/sdch_dictionary.cc
@@ -0,0 +1,170 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/sdch_dictionary.h" + +#include "base/time/clock.h" +#include "base/time/default_clock.h" +#include "base/values.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" + +namespace { + +bool DomainMatch(const GURL& gurl, const std::string& restriction) { + // TODO(jar): This is not precisely a domain match definition. + return gurl.DomainIs(restriction.data(), restriction.size()); +} + +} // namespace + +namespace net { + +SdchDictionary::SdchDictionary(const std::string& dictionary_text, + size_t offset, + const std::string& client_hash, + const std::string& server_hash, + const GURL& gurl, + const std::string& domain, + const std::string& path, + const base::Time& expiration, + const std::set<int>& ports) + : text_(dictionary_text, offset), + client_hash_(client_hash), + server_hash_(server_hash), + url_(gurl), + domain_(domain), + path_(path), + expiration_(expiration), + ports_(ports), + clock_(new base::DefaultClock) { +} + +SdchDictionary::SdchDictionary(const SdchDictionary& rhs) + : text_(rhs.text_), + client_hash_(rhs.client_hash_), + server_hash_(rhs.server_hash_), + url_(rhs.url_), + domain_(rhs.domain_), + path_(rhs.path_), + expiration_(rhs.expiration_), + ports_(rhs.ports_), + clock_(new base::DefaultClock) { +} + +SdchDictionary::~SdchDictionary() { +} + +// Security functions restricting loads and use of dictionaries. + +// static +SdchProblemCode SdchDictionary::CanSet(const std::string& domain, + const std::string& path, + const std::set<int>& ports, + const GURL& dictionary_url) { + /* + * A dictionary is invalid and must not be stored if any of the following are + * true: + * 1. The dictionary has no Domain attribute. + * 2. The effective host name that derives from the referer URL host name does + * not domain-match the Domain attribute. + * 3. The Domain attribute is a top level domain. + * 4. The referer URL host is a host domain name (not IP address) and has the + * form HD, where D is the value of the Domain attribute, and H is a string + * that contains one or more dots. + * 5. If the dictionary has a Port attribute and the referer URL's port + * was not in the list. + */ + + // TODO(jar): Redirects in dictionary fetches might plausibly be problematic, + // and hence the conservative approach is to not allow any redirects (if there + // were any... then don't allow the dictionary to be set). + + if (domain.empty()) + return SDCH_DICTIONARY_MISSING_DOMAIN_SPECIFIER; // Domain is required. + + if (registry_controlled_domains::GetDomainAndRegistry( + domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) + .empty()) { + return SDCH_DICTIONARY_SPECIFIES_TOP_LEVEL_DOMAIN; // domain was a TLD. + } + + if (!DomainMatch(dictionary_url, domain)) + return SDCH_DICTIONARY_DOMAIN_NOT_MATCHING_SOURCE_URL; + + std::string referrer_url_host = dictionary_url.host(); + size_t postfix_domain_index = referrer_url_host.rfind(domain); + // See if it is indeed a postfix, or just an internal string. + if (referrer_url_host.size() == postfix_domain_index + domain.size()) { + // It is a postfix... so check to see if there's a dot in the prefix. + size_t end_of_host_index = referrer_url_host.find_first_of('.'); + if (referrer_url_host.npos != end_of_host_index && + end_of_host_index < postfix_domain_index) { + return SDCH_DICTIONARY_REFERER_URL_HAS_DOT_IN_PREFIX; + } + } + + if (!ports.empty() && 0 == ports.count(dictionary_url.EffectiveIntPort())) + return SDCH_DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL; + + return SDCH_OK; +} + +SdchProblemCode SdchDictionary::CanUse(const GURL& target_url) const { + /* + * 1. The request URL's host name domain-matches the Domain attribute of the + * dictionary. + * 2. If the dictionary has a Port attribute, the request port is one of the + * ports listed in the Port attribute. + * 3. The request URL path-matches the path attribute of the dictionary. + * We can override (ignore) item (4) only when we have explicitly enabled + * HTTPS support AND the dictionary acquisition scheme matches the target + * url scheme. + */ + if (!DomainMatch(target_url, domain_)) + return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN; + + if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort())) + return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST; + + if (path_.size() && !PathMatch(target_url.path(), path_)) + return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH; + + if (target_url.SchemeIsSecure() != url_.SchemeIsSecure()) + return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; + + // TODO(jar): Remove overly restrictive failsafe test (added per security + // review) when we have a need to be more general. + if (!target_url.SchemeIsHTTPOrHTTPS()) + return SDCH_ATTEMPT_TO_DECODE_NON_HTTP_DATA; + + return SDCH_OK; +} + +// static +bool SdchDictionary::PathMatch(const std::string& path, + const std::string& restriction) { + /* Must be either: + * 1. P2 is equal to P1 + * 2. P2 is a prefix of P1 and either the final character in P2 is "/" + * or the character following P2 in P1 is "/". + */ + if (path == restriction) + return true; + size_t prefix_length = restriction.size(); + if (prefix_length > path.size()) + return false; // Can't be a prefix. + if (0 != path.compare(0, prefix_length, restriction)) + return false; + return restriction[prefix_length - 1] == '/' || path[prefix_length] == '/'; +} + +bool SdchDictionary::Expired() const { + return clock_->Now() > expiration_; +} + +void SdchDictionary::SetClockForTesting(scoped_ptr<base::Clock> clock) { + clock_ = clock.Pass(); +} + +} // namespace net
diff --git a/net/base/sdch_dictionary.h b/net/base/sdch_dictionary.h new file mode 100644 index 0000000..696dcdf --- /dev/null +++ b/net/base/sdch_dictionary.h
@@ -0,0 +1,114 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_SDCH_DICTIONARY_H_ +#define NET_BASE_SDCH_DICTIONARY_H_ + +#include <set> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "net/base/net_export.h" +#include "net/base/sdch_problem_codes.h" +#include "url/gurl.h" + +namespace base { +class Clock; +class Value; +} + +namespace net { + +// Contains all information for an SDCH dictionary. This class is intended +// to be used with a RefCountedData<> wrappers. These dictionaries +// are vended by SdchManager; see sdch_manager.h for details. +class NET_EXPORT_PRIVATE SdchDictionary { + public: + // Construct a vc-diff usable dictionary from the dictionary_text starting + // at the given offset. The supplied client_hash should be used to + // advertise the dictionary's availability relative to the suppplied URL. + SdchDictionary(const std::string& dictionary_text, + size_t offset, + const std::string& client_hash, + const std::string& server_hash, + const GURL& url, + const std::string& domain, + const std::string& path, + const base::Time& expiration, + const std::set<int>& ports); + + ~SdchDictionary(); + + // Sdch filters can get our text to use in decoding compressed data. + const std::string& text() const { return text_; } + + const GURL& url() const { return url_; } + const std::string& client_hash() const { return client_hash_; } + const std::string& server_hash() const { return server_hash_; } + const std::string& domain() const { return domain_; } + const std::string& path() const { return path_; } + const base::Time& expiration() const { return expiration_; } + const std::set<int>& ports() const { return ports_; } + + // Security methods to check if we can establish a new dictionary with the + // given data, that arrived in response to get of dictionary_url. + static SdchProblemCode CanSet(const std::string& domain, + const std::string& path, + const std::set<int>& ports, + const GURL& dictionary_url); + + // Security method to check if we can use a dictionary to decompress a + // target that arrived with a reference to this dictionary. + SdchProblemCode CanUse(const GURL& referring_url) const; + + // Compare paths to see if they "match" for dictionary use. + static bool PathMatch(const std::string& path, + const std::string& restriction); + + // Is this dictionary expired? + bool Expired() const; + + void SetClockForTesting(scoped_ptr<base::Clock> clock); + + private: + friend class base::RefCountedData<SdchDictionary>; + + // Private copy-constructor to support RefCountedData<>, which requires + // that an object stored in it be either DefaultConstructible or + // CopyConstructible + SdchDictionary(const SdchDictionary& rhs); + + // The actual text of the dictionary. + std::string text_; + + // Part of the hash of text_ that the client uses to advertise the fact that + // it has a specific dictionary pre-cached. + std::string client_hash_; + + // Part of the hash of text_ that the server uses to identify the + // dictionary it wants used for decoding. + std::string server_hash_; + + // The GURL that arrived with the text_ in a URL request to specify where + // this dictionary may be used. + const GURL url_; + + // Metadate "headers" in before dictionary text contained the following: + // Each dictionary payload consists of several headers, followed by the text + // of the dictionary. The following are the known headers. + const std::string domain_; + const std::string path_; + const base::Time expiration_; // Implied by max-age. + const std::set<int> ports_; + + scoped_ptr<base::Clock> clock_; + + void operator=(const SdchDictionary&) = delete; +}; + +} // namespace net + +#endif // NET_BASE_SDCH_DICTIONARY_H_
diff --git a/net/base/sdch_dictionary_unittest.cc b/net/base/sdch_dictionary_unittest.cc new file mode 100644 index 0000000..d9fd92e --- /dev/null +++ b/net/base/sdch_dictionary_unittest.cc
@@ -0,0 +1,132 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/base/sdch_dictionary.h" + +#include <set> +#include <string> + +#include "net/base/sdch_problem_codes.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +TEST(SdchDictionaryTest, CanSet) { + SdchProblemCode (*CanSet)(const std::string& domain, const std::string& path, + const std::set<int>& ports, + const GURL& dictionary_url) = + SdchDictionary::CanSet; + + std::set<int> single_port; + single_port.insert(1); + + std::set<int> dual_port; + dual_port.insert(2); + dual_port.insert(3); + + // Not testing specific error codes; that's implementation, not behavior. + EXPECT_EQ(SDCH_OK, CanSet("www.google.com", "", std::set<int>(), + GURL("http://www.google.com/dictionary"))); + EXPECT_NE(SDCH_OK, CanSet("", "", std::set<int>(), + GURL("http://www.google.com/dictionary"))); + EXPECT_NE(SDCH_OK, + CanSet("com", "", std::set<int>(), GURL("http://com/dictionary"))); + EXPECT_NE(SDCH_OK, CanSet("www.google.com", "", std::set<int>(), + GURL("http://www.simple.com/dictionary"))); + EXPECT_EQ(SDCH_OK, CanSet(".google.com", "", std::set<int>(), + GURL("http://www.google.com/dictionary"))); + EXPECT_NE(SDCH_OK, CanSet("google.com", "", std::set<int>(), + GURL("http://www.google.com/dictionary"))); + EXPECT_EQ(SDCH_OK, CanSet("www.google.com", "", single_port, + GURL("http://www.google.com:1/dictionary"))); + EXPECT_EQ(SDCH_OK, CanSet("www.google.com", "", dual_port, + GURL("http://www.google.com:2/dictionary"))); + EXPECT_NE(SDCH_OK, CanSet("www.google.com", "", single_port, + GURL("http://www.google.com:10/dictionary"))); + EXPECT_NE(SDCH_OK, CanSet("www.google.com", "", dual_port, + GURL("http://www.google.com:10/dictionary"))); +} + +TEST(SdchDictionaryTest, CanUse) { + std::set<int> dual_port; + dual_port.insert(2); + dual_port.insert(3); + + SdchDictionary test_dictionary_1( + "xyzzy", 0u, // text, offset + "ch", "sh", // client hash, server hash + GURL("http://www.example.com"), "www.example.com", + "/url", // domain, path + base::Time::Now() + base::TimeDelta::FromSeconds(1), // expiration + dual_port); // ports + + // Not testing specific error codes; that's implementation, not behavior. + EXPECT_EQ(SDCH_OK, + test_dictionary_1.CanUse(GURL("http://www.example.com:2/url"))); + EXPECT_NE(SDCH_OK, + test_dictionary_1.CanUse(GURL("http://www.google.com:2/url"))); + EXPECT_NE(SDCH_OK, + test_dictionary_1.CanUse(GURL("http://www.example.com:4/url"))); + EXPECT_NE(SDCH_OK, + test_dictionary_1.CanUse(GURL("http://www.example.com:2/wurl"))); + EXPECT_NE(SDCH_OK, + test_dictionary_1.CanUse(GURL("https://www.example.com:2/url"))); + EXPECT_NE(SDCH_OK, + test_dictionary_1.CanUse(GURL("ws://www.example.com:2/url"))); +} + +TEST(SdchDictionaryTest, PathMatch) { + bool (*PathMatch)(const std::string& path, const std::string& restriction) = + SdchDictionary::PathMatch; + // Perfect match is supported. + EXPECT_TRUE(PathMatch("/search", "/search")); + EXPECT_TRUE(PathMatch("/search/", "/search/")); + + // Prefix only works if last character of restriction is a slash, or first + // character in path after a match is a slash. Validate each case separately. + + // Rely on the slash in the path (not at the end of the restriction). + EXPECT_TRUE(PathMatch("/search/something", "/search")); + EXPECT_TRUE(PathMatch("/search/s", "/search")); + EXPECT_TRUE(PathMatch("/search/other", "/search")); + EXPECT_TRUE(PathMatch("/search/something", "/search")); + + // Rely on the slash at the end of the restriction. + EXPECT_TRUE(PathMatch("/search/something", "/search/")); + EXPECT_TRUE(PathMatch("/search/s", "/search/")); + EXPECT_TRUE(PathMatch("/search/other", "/search/")); + EXPECT_TRUE(PathMatch("/search/something", "/search/")); + + // Make sure less that sufficient prefix match is false. + EXPECT_FALSE(PathMatch("/sear", "/search")); + EXPECT_FALSE(PathMatch("/", "/search")); + EXPECT_FALSE(PathMatch(std::string(), "/search")); + + // Add examples with several levels of direcories in the restriction. + EXPECT_FALSE(PathMatch("/search/something", "search/s")); + EXPECT_FALSE(PathMatch("/search/", "/search/s")); + + // Make sure adding characters to path will also fail. + EXPECT_FALSE(PathMatch("/searching", "/search/")); + EXPECT_FALSE(PathMatch("/searching", "/search")); + + // Make sure we're case sensitive. + EXPECT_FALSE(PathMatch("/ABC", "/abc")); + EXPECT_FALSE(PathMatch("/abc", "/ABC")); +} + +TEST(SdchDictionaryTest, Expired) { + EXPECT_TRUE( + SdchDictionary("xyzzy", 0u, "ch", "sh", GURL("http://www.example.com"), + "www.example.com", "/url", + base::Time::Now() - base::TimeDelta::FromSeconds(1), + std::set<int>()).Expired()); + EXPECT_FALSE( + SdchDictionary("xyzzy", 0u, "ch", "sh", GURL("http://www.example.com"), + "www.example.com", "/url", + base::Time::Now() + base::TimeDelta::FromSeconds(1), + std::set<int>()).Expired()); +} + +} // namespace net
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc index 34fc76af..0f9b96d 100644 --- a/net/base/sdch_manager.cc +++ b/net/base/sdch_manager.cc
@@ -12,7 +12,6 @@ #include "base/time/default_clock.h" #include "base/values.h" #include "crypto/sha2.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/sdch_observer.h" #include "net/url_request/url_request_http_job.h" @@ -45,165 +44,6 @@ // static bool SdchManager::g_secure_scheme_supported_ = true; -SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, - size_t offset, - const std::string& client_hash, - const std::string& server_hash, - const GURL& gurl, - const std::string& domain, - const std::string& path, - const base::Time& expiration, - const std::set<int>& ports) - : text_(dictionary_text, offset), - client_hash_(client_hash), - server_hash_(server_hash), - url_(gurl), - domain_(domain), - path_(path), - expiration_(expiration), - ports_(ports), - clock_(new base::DefaultClock) { -} - -SdchManager::Dictionary::Dictionary(const SdchManager::Dictionary& rhs) - : text_(rhs.text_), - client_hash_(rhs.client_hash_), - server_hash_(rhs.server_hash_), - url_(rhs.url_), - domain_(rhs.domain_), - path_(rhs.path_), - expiration_(rhs.expiration_), - ports_(rhs.ports_), - clock_(new base::DefaultClock) { -} - -SdchManager::Dictionary::~Dictionary() {} - -// Security functions restricting loads and use of dictionaries. - -// static -SdchProblemCode SdchManager::Dictionary::CanSet(const std::string& domain, - const std::string& path, - const std::set<int>& ports, - const GURL& dictionary_url) { - /* - A dictionary is invalid and must not be stored if any of the following are - true: - 1. The dictionary has no Domain attribute. - 2. The effective host name that derives from the referer URL host name does - not domain-match the Domain attribute. - 3. The Domain attribute is a top level domain. - 4. The referer URL host is a host domain name (not IP address) and has the - form HD, where D is the value of the Domain attribute, and H is a string - that contains one or more dots. - 5. If the dictionary has a Port attribute and the referer URL's port was not - in the list. - */ - - // TODO(jar): Redirects in dictionary fetches might plausibly be problematic, - // and hence the conservative approach is to not allow any redirects (if there - // were any... then don't allow the dictionary to be set). - - if (domain.empty()) - return SDCH_DICTIONARY_MISSING_DOMAIN_SPECIFIER; // Domain is required. - - if (registry_controlled_domains::GetDomainAndRegistry( - domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) - .empty()) { - return SDCH_DICTIONARY_SPECIFIES_TOP_LEVEL_DOMAIN; // domain was a TLD. - } - - if (!Dictionary::DomainMatch(dictionary_url, domain)) - return SDCH_DICTIONARY_DOMAIN_NOT_MATCHING_SOURCE_URL; - - std::string referrer_url_host = dictionary_url.host(); - size_t postfix_domain_index = referrer_url_host.rfind(domain); - // See if it is indeed a postfix, or just an internal string. - if (referrer_url_host.size() == postfix_domain_index + domain.size()) { - // It is a postfix... so check to see if there's a dot in the prefix. - size_t end_of_host_index = referrer_url_host.find_first_of('.'); - if (referrer_url_host.npos != end_of_host_index && - end_of_host_index < postfix_domain_index) { - return SDCH_DICTIONARY_REFERER_URL_HAS_DOT_IN_PREFIX; - } - } - - if (!ports.empty() && 0 == ports.count(dictionary_url.EffectiveIntPort())) - return SDCH_DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL; - - return SDCH_OK; -} - -SdchProblemCode SdchManager::Dictionary::CanUse( - const GURL& target_url) const { - /* - 1. The request URL's host name domain-matches the Domain attribute of the - dictionary. - 2. If the dictionary has a Port attribute, the request port is one of the - ports listed in the Port attribute. - 3. The request URL path-matches the path attribute of the dictionary. - 4. The request is not an HTTPS request. - We can override (ignore) item (4) only when we have explicitly enabled - HTTPS support AND the dictionary acquisition scheme matches the target - url scheme. - */ - if (!DomainMatch(target_url, domain_)) - return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN; - - if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort())) - return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST; - - if (path_.size() && !PathMatch(target_url.path(), path_)) - return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH; - - if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure()) - return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; - - if (target_url.SchemeIsSecure() != url_.SchemeIsSecure()) - return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; - - // TODO(jar): Remove overly restrictive failsafe test (added per security - // review) when we have a need to be more general. - if (!target_url.SchemeIsHTTPOrHTTPS()) - return SDCH_ATTEMPT_TO_DECODE_NON_HTTP_DATA; - - return SDCH_OK; -} - -// static -bool SdchManager::Dictionary::PathMatch(const std::string& path, - const std::string& restriction) { - /* Must be either: - 1. P2 is equal to P1 - 2. P2 is a prefix of P1 and either the final character in P2 is "/" or the - character following P2 in P1 is "/". - */ - if (path == restriction) - return true; - size_t prefix_length = restriction.size(); - if (prefix_length > path.size()) - return false; // Can't be a prefix. - if (0 != path.compare(0, prefix_length, restriction)) - return false; - return restriction[prefix_length - 1] == '/' || path[prefix_length] == '/'; -} - -// static -bool SdchManager::Dictionary::DomainMatch(const GURL& gurl, - const std::string& restriction) { - // TODO(jar): This is not precisely a domain match definition. - return gurl.DomainIs(restriction.data(), restriction.size()); -} - -bool SdchManager::Dictionary::Expired() const { - return clock_->Now() > expiration_; -} - -void SdchManager::Dictionary::SetClockForTesting( - scoped_ptr<base::Clock> clock) { - clock_ = clock.Pass(); -} - SdchManager::DictionarySet::DictionarySet() {} SdchManager::DictionarySet::~DictionarySet() {} @@ -221,7 +61,7 @@ return result; } -const SdchManager::Dictionary* SdchManager::DictionarySet::GetDictionary( +const SdchDictionary* SdchManager::DictionarySet::GetDictionary( const std::string& hash) const { auto it = dictionaries_.find(hash); if (it == dictionaries_.end()) @@ -236,8 +76,7 @@ void SdchManager::DictionarySet::AddDictionary( const std::string& server_hash, - const scoped_refptr<base::RefCountedData<SdchManager::Dictionary>>& - dictionary) { + const scoped_refptr<base::RefCountedData<SdchDictionary>>& dictionary) { DCHECK(dictionaries_.end() == dictionaries_.find(server_hash)); dictionaries_[server_hash] = dictionary; @@ -430,6 +269,8 @@ int count = 0; scoped_ptr<SdchManager::DictionarySet> result(new DictionarySet); for (const auto& entry: dictionaries_) { + if (!secure_scheme_supported() && target_url.SchemeIsSecure()) + continue; if (entry.second->data.CanUse(target_url) != SDCH_OK) continue; if (entry.second->data.Expired()) @@ -458,6 +299,11 @@ if (it == dictionaries_.end()) return result.Pass(); + if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure()) { + *problem_code = SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; + return result.Pass(); + } + *problem_code = it->second->data.CanUse(target_url); if (*problem_code != SDCH_OK) return result.Pass(); @@ -587,18 +433,18 @@ if (rv != SDCH_OK) return rv; - rv = Dictionary::CanSet(domain, path, ports, dictionary_url_normalized); + rv = SdchDictionary::CanSet(domain, path, ports, dictionary_url_normalized); if (rv != SDCH_OK) return rv; UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); DVLOG(1) << "Loaded dictionary with client hash " << client_hash << " and server hash " << server_hash; - Dictionary dictionary(dictionary_text, header_end + 2, client_hash, - server_hash, dictionary_url_normalized, domain, path, - expiration, ports); + SdchDictionary dictionary(dictionary_text, header_end + 2, client_hash, + server_hash, dictionary_url_normalized, domain, + path, expiration, ports); dictionaries_[server_hash] = - new base::RefCountedData<Dictionary>(dictionary); + new base::RefCountedData<SdchDictionary>(dictionary); if (server_hash_p) *server_hash_p = server_hash;
diff --git a/net/base/sdch_manager.h b/net/base/sdch_manager.h index 19dc710..42e6acd 100644 --- a/net/base/sdch_manager.h +++ b/net/base/sdch_manager.h
@@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file contains the SdchManager class and two nested classes -// (Dictionary, DictionarySet). SdchManager::Dictionary contains all -// of the information about an SDCH dictionary. The manager is -// responsible for storing those dictionaries, and provides access to -// them through DictionarySet objects. A DictionarySet is an object -// whose lifetime is under the control of the consumer. It is a -// reference to a set of dictionaries, and guarantees that none of -// those dictionaries will be destroyed while the DictionarySet -// reference is alive. +// This file contains the SdchManager class and the DictionarySet +// nested class. The manager is responsible for storing all +// SdchDictionarys, and provides access to them through DictionarySet +// objects. A DictionarySet is an object whose lifetime is under the +// control of the consumer. It is a reference to a set of +// dictionaries, and guarantees that none of those dictionaries will +// be destroyed while the DictionarySet reference is alive. #ifndef NET_BASE_SDCH_MANAGER_H_ #define NET_BASE_SDCH_MANAGER_H_ @@ -26,13 +24,13 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/threading/thread_checker.h" -#include "base/time/time.h" #include "net/base/net_export.h" +#include "net/base/sdch_dictionary.h" #include "net/base/sdch_problem_codes.h" -#include "url/gurl.h" + +class GURL; namespace base { -class Clock; class Value; } @@ -56,97 +54,10 @@ // a DictionarySet object refers to it; see below. class NET_EXPORT SdchManager { public: - class Dictionary; - typedef std::map<std::string, scoped_refptr<base::RefCountedData<Dictionary>>> + typedef std::map<std::string, + scoped_refptr<base::RefCountedData<SdchDictionary>>> DictionaryMap; - class NET_EXPORT_PRIVATE Dictionary { - public: - // Construct a vc-diff usable dictionary from the dictionary_text starting - // at the given offset. The supplied client_hash should be used to - // advertise the dictionary's availability relative to the suppplied URL. - Dictionary(const std::string& dictionary_text, - size_t offset, - const std::string& client_hash, - const std::string& server_hash, - const GURL& url, - const std::string& domain, - const std::string& path, - const base::Time& expiration, - const std::set<int>& ports); - - ~Dictionary(); - - // Sdch filters can get our text to use in decoding compressed data. - const std::string& text() const { return text_; } - - const GURL& url() const { return url_; } - const std::string& client_hash() const { return client_hash_; } - const std::string& server_hash() const { return server_hash_; } - const std::string& domain() const { return domain_; } - const std::string& path() const { return path_; } - const base::Time& expiration() const { return expiration_; } - const std::set<int>& ports() const { return ports_; } - - // Security methods to check if we can establish a new dictionary with the - // given data, that arrived in response to get of dictionary_url. - static SdchProblemCode CanSet(const std::string& domain, - const std::string& path, - const std::set<int>& ports, - const GURL& dictionary_url); - - // Security method to check if we can use a dictionary to decompress a - // target that arrived with a reference to this dictionary. - SdchProblemCode CanUse(const GURL& referring_url) const; - - // Compare paths to see if they "match" for dictionary use. - static bool PathMatch(const std::string& path, - const std::string& restriction); - - // Compare domains to see if the "match" for dictionary use. - static bool DomainMatch(const GURL& url, const std::string& restriction); - - // Is this dictionary expired? - bool Expired() const; - - void SetClockForTesting(scoped_ptr<base::Clock> clock); - - private: - friend class base::RefCountedData<Dictionary>; - - // Private copy-constructor to support RefCountedData<>, which requires - // that an object stored in it be either DefaultConstructible or - // CopyConstructible - Dictionary(const Dictionary& rhs); - - // The actual text of the dictionary. - std::string text_; - - // Part of the hash of text_ that the client uses to advertise the fact that - // it has a specific dictionary pre-cached. - std::string client_hash_; - - // Part of the hash of text_ that the server uses to identify the - // dictionary it wants used for decoding. - std::string server_hash_; - - // The GURL that arrived with the text_ in a URL request to specify where - // this dictionary may be used. - const GURL url_; - - // Metadate "headers" in before dictionary text contained the following: - // Each dictionary payload consists of several headers, followed by the text - // of the dictionary. The following are the known headers. - const std::string domain_; - const std::string path_; - const base::Time expiration_; // Implied by max-age. - const std::set<int> ports_; - - scoped_ptr<base::Clock> clock_; - - void operator=(const Dictionary&) = delete; - }; - // A handle for one or more dictionaries which will keep the dictionaries // alive and accessible for the handle's lifetime. class NET_EXPORT_PRIVATE DictionarySet { @@ -160,7 +71,7 @@ // is guaranteed to be valid for the lifetime of the DictionarySet. // Returns NULL if hash is not a valid server hash for a dictionary // named by DictionarySet. - const SdchManager::Dictionary* GetDictionary(const std::string& hash) const; + const SdchDictionary* GetDictionary(const std::string& hash) const; bool Empty() const; @@ -169,9 +80,9 @@ friend class SdchManager; DictionarySet(); - void AddDictionary(const std::string& server_hash, - const scoped_refptr<base::RefCountedData< - SdchManager::Dictionary>>& dictionary); + void AddDictionary( + const std::string& server_hash, + const scoped_refptr<base::RefCountedData<SdchDictionary>>& dictionary); DictionaryMap dictionaries_;
diff --git a/net/base/sdch_manager_unittest.cc b/net/base/sdch_manager_unittest.cc index 67871fa0..cbee86b 100644 --- a/net/base/sdch_manager_unittest.cc +++ b/net/base/sdch_manager_unittest.cc
@@ -419,46 +419,6 @@ GURL("http://" + dictionary_domain))); } -TEST_F(SdchManagerTest, PathMatch) { - bool (*PathMatch)(const std::string& path, const std::string& restriction) = - SdchManager::Dictionary::PathMatch; - // Perfect match is supported. - EXPECT_TRUE(PathMatch("/search", "/search")); - EXPECT_TRUE(PathMatch("/search/", "/search/")); - - // Prefix only works if last character of restriction is a slash, or first - // character in path after a match is a slash. Validate each case separately. - - // Rely on the slash in the path (not at the end of the restriction). - EXPECT_TRUE(PathMatch("/search/something", "/search")); - EXPECT_TRUE(PathMatch("/search/s", "/search")); - EXPECT_TRUE(PathMatch("/search/other", "/search")); - EXPECT_TRUE(PathMatch("/search/something", "/search")); - - // Rely on the slash at the end of the restriction. - EXPECT_TRUE(PathMatch("/search/something", "/search/")); - EXPECT_TRUE(PathMatch("/search/s", "/search/")); - EXPECT_TRUE(PathMatch("/search/other", "/search/")); - EXPECT_TRUE(PathMatch("/search/something", "/search/")); - - // Make sure less that sufficient prefix match is false. - EXPECT_FALSE(PathMatch("/sear", "/search")); - EXPECT_FALSE(PathMatch("/", "/search")); - EXPECT_FALSE(PathMatch(std::string(), "/search")); - - // Add examples with several levels of direcories in the restriction. - EXPECT_FALSE(PathMatch("/search/something", "search/s")); - EXPECT_FALSE(PathMatch("/search/", "/search/s")); - - // Make sure adding characters to path will also fail. - EXPECT_FALSE(PathMatch("/searching", "/search/")); - EXPECT_FALSE(PathMatch("/searching", "/search")); - - // Make sure we're case sensitive. - EXPECT_FALSE(PathMatch("/ABC", "/abc")); - EXPECT_FALSE(PathMatch("/abc", "/ABC")); -} - // The following are only applicable while we have a latency test in the code, // and can be removed when that functionality is stripped. TEST_F(SdchManagerTest, LatencyTestControls) { @@ -636,9 +596,8 @@ target_gurl, server_hash, &problem_code).Pass()); ASSERT_TRUE(hash_set); ASSERT_EQ(SDCH_OK, problem_code); - const_cast<SdchManager::Dictionary*>( - hash_set->GetDictionary(server_hash))->SetClockForTesting( - clock.Pass()); + const_cast<SdchDictionary*>(hash_set->GetDictionary(server_hash)) + ->SetClockForTesting(clock.Pass()); // Make sure it's not visible for advertisement, but is visible // if looked up by hash.
diff --git a/net/base/sdch_problem_code_list.h b/net/base/sdch_problem_code_list.h index 744133a96..f0e2d49 100644 --- a/net/base/sdch_problem_code_list.h +++ b/net/base/sdch_problem_code_list.h
@@ -33,7 +33,7 @@ SDCH_PROBLEM_CODE(DICTIONARY_FOUND_HAS_WRONG_SCHEME, 13) SDCH_PROBLEM_CODE(DICTIONARY_HASH_NOT_FOUND, 14) SDCH_PROBLEM_CODE(DICTIONARY_HASH_MALFORMED, 15) -SDCH_PROBLEM_CODE(DICTIONARY_FOUND_EXPIRED, 16) +// defunct = 16, no longer used // Dictionary saving problems. SDCH_PROBLEM_CODE(DICTIONARY_HAS_NO_HEADER, 20)
diff --git a/net/cert/cert_net_fetcher.h b/net/cert/cert_net_fetcher.h new file mode 100644 index 0000000..2d19e14 --- /dev/null +++ b/net/cert/cert_net_fetcher.h
@@ -0,0 +1,106 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CERT_CERT_NET_FETCHER_H_ +#define NET_CERT_CERT_NET_FETCHER_H_ + +#include <vector> + +#include "base/callback.h" +#include "net/base/net_errors.h" +#include "net/base/net_export.h" + +class GURL; + +namespace net { + +class URLRequestContext; + +// CertNetFetcher is an asynchronous interface for fetching AIA URLs and CRL +// URLs. +// +// ------------------------- +// Cancellation of requests +// ------------------------- +// +// * Network requests started by the CertNetFetcher can be cancelled by +// deleting the Request object. Cancellation means the request's callback +// will no longer be invoked. +// +// * If the CertNetFetcher is deleted then any outstanding +// requests are automatically cancelled. +// +// * Cancelling a request within the execution of a callback is allowed. +// +// * Deleting the CertNetFetcher from within the execution of a callback is +// allowed. +// +// ------------------------- +// Threading +// ------------------------- +// +// The CertNetFetcher is expected to be operated from a single thread, which has +// an IO message loop. The URLRequestContext will be accessed from this same +// thread, and callbacks will be posted to this message loop. +// +// For more details see the design document: +// https://docs.google.com/a/chromium.org/document/d/1CdS9YOnPdAyVZBJqHY7ZJ6tUlU71OCvX8kHnaVhf144/edit +class NET_EXPORT CertNetFetcher { + public: + class Request { + public: + virtual ~Request() {} + }; + + // Callback invoked on request completion. If the Error is OK, then the + // vector contains the response bytes. + using FetchCallback = + base::Callback<void(Error, const std::vector<uint8_t>&)>; + + // This value can be used in place of timeout or max size limits. + enum { DEFAULT = -1 }; + + CertNetFetcher() {} + + // Deletion implicitly cancels any outstanding requests. + virtual ~CertNetFetcher() {} + + // The Fetch*() methods start an asynchronous request which can be cancelled + // by deleting the returned Request. Here is the meaning of the common + // parameters: + // + // * url -- The http:// URL to fetch. + // * timeout_seconds -- The maximum allowed duration for the fetch job. If + // this delay is exceeded then the request will fail. To use a default + // timeout pass DEFAULT. + // * max_response_bytes -- The maximum size of the response body. If this + // size is exceeded then the request will fail. To use a default timeout + // pass DEFAULT. + // * callback -- The callback that will be invoked on completion of the job. + + virtual WARN_UNUSED_RESULT scoped_ptr<Request> FetchCaIssuers( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) = 0; + + virtual WARN_UNUSED_RESULT scoped_ptr<Request> FetchCrl( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) = 0; + + virtual WARN_UNUSED_RESULT scoped_ptr<Request> FetchOcsp( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(CertNetFetcher); +}; + +} // namespace net + +#endif // NET_CERT_NET_CERT_NET_FETCHER_H_
diff --git a/net/cert_net/README b/net/cert_net/README new file mode 100644 index 0000000..67fe3ba --- /dev/null +++ b/net/cert_net/README
@@ -0,0 +1,6 @@ +cert_net/ contains certificate functionality that depends on network loading (OCSP, CRL, AIA fetching). + +Conceptually certificates (net/cert/) is a separable concept from net/ and may +end up becoming its own build target. This file organization encourages not +adding dependencies in cert/ for doing network loading. Instead that code +should be placed here.
diff --git a/net/cert_net/cert_net_fetcher_impl.cc b/net/cert_net/cert_net_fetcher_impl.cc new file mode 100644 index 0000000..7b119ca --- /dev/null +++ b/net/cert_net/cert_net_fetcher_impl.cc
@@ -0,0 +1,550 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert_net/cert_net_fetcher_impl.h" + +#include "base/callback_helpers.h" +#include "base/containers/linked_list.h" +#include "base/logging.h" +#include "base/numerics/safe_math.h" +#include "base/stl_util.h" +#include "base/timer/timer.h" +#include "net/base/load_flags.h" +#include "net/url_request/redirect_info.h" +#include "net/url_request/url_request_context.h" + +// TODO(eroman): Add support for POST parameters. +// TODO(eroman): Add controls for bypassing the cache. +// TODO(eroman): Add a maximum number of in-flight jobs/requests. +// TODO(eroman): Add NetLog integration. + +namespace net { + +namespace { + +// The size of the buffer used for reading the response body of the URLRequest. +const int kReadBufferSizeInBytes = 4096; + +// The maximum size in bytes for the response body when fetching a CRL. +const int kMaxResponseSizeInBytesForCrl = 5 * 1024 * 1024; + +// The maximum size in bytes for the response body when fetching an AIA URL +// (caIssuers/OCSP). +const int kMaxResponseSizeInBytesForAia = 64 * 1024; + +// The default timeout in seconds for fetch requests. +const int kTimeoutSeconds = 15; + +// Policy for which URLs are allowed to be fetched. This is called both for the +// initial URL and for each redirect. Returns OK on success or a net error +// code on failure. +Error CanFetchUrl(const GURL& url) { + if (!url.SchemeIs("http")) + return ERR_DISALLOWED_URL_SCHEME; + return OK; +} + +base::TimeDelta GetTimeout(int timeout_milliseconds) { + if (timeout_milliseconds == CertNetFetcher::DEFAULT) + return base::TimeDelta::FromSeconds(kTimeoutSeconds); + return base::TimeDelta::FromMilliseconds(timeout_milliseconds); +} + +size_t GetMaxResponseBytes(int max_response_bytes, + size_t default_max_response_bytes) { + if (max_response_bytes == CertNetFetcher::DEFAULT) + return default_max_response_bytes; + + // Ensure that the specified limit is not negative, and cannot result in an + // overflow while reading. + base::CheckedNumeric<size_t> check(max_response_bytes); + check += kReadBufferSizeInBytes; + DCHECK(check.IsValid()); + + return max_response_bytes; +} + +enum HttpMethod { + HTTP_METHOD_GET, + HTTP_METHOD_POST, +}; + +} // namespace + +// CertNetFetcherImpl::RequestImpl tracks an outstanding call to Fetch(). +class CertNetFetcherImpl::RequestImpl : public CertNetFetcher::Request, + public base::LinkNode<RequestImpl> { + public: + RequestImpl(Job* job, const FetchCallback& callback) + : callback_(callback), job_(job) { + DCHECK(!callback.is_null()); + } + + // Deletion cancels the outstanding request. + ~RequestImpl() override; + + void OnJobCancelled(Job* job) { + DCHECK_EQ(job_, job); + job_ = nullptr; + callback_.Reset(); + } + + void OnJobCompleted(Job* job, + Error error, + const std::vector<uint8_t>& response_body) { + DCHECK_EQ(job_, job); + job_ = nullptr; + base::ResetAndReturn(&callback_).Run(error, response_body); + } + + private: + // The callback to invoke when the request has completed. + FetchCallback callback_; + + // A non-owned pointer to the job that is executing the request. + Job* job_; + + private: + DISALLOW_COPY_AND_ASSIGN(RequestImpl); +}; + +struct CertNetFetcherImpl::RequestParams { + RequestParams(); + + bool operator<(const RequestParams& other) const; + + GURL url; + HttpMethod http_method; + size_t max_response_bytes; + + // If set to a value <= 0 then means "no timeout". + base::TimeDelta timeout; + + // IMPORTANT: When adding fields to this structure, update operator<(). + + private: + DISALLOW_COPY_AND_ASSIGN(RequestParams); +}; + +CertNetFetcherImpl::RequestParams::RequestParams() + : http_method(HTTP_METHOD_GET), max_response_bytes(0) { +} + +bool CertNetFetcherImpl::RequestParams::operator<( + const RequestParams& other) const { + if (url != other.url) + return url < other.url; + if (http_method != other.http_method) + return http_method < other.http_method; + if (max_response_bytes != other.max_response_bytes) + return max_response_bytes < other.max_response_bytes; + return timeout < other.timeout; +} + +// CertNetFetcherImpl::Job tracks an outstanding URLRequest as well as all of +// the pending requests for it. +class CertNetFetcherImpl::Job : public URLRequest::Delegate { + public: + Job(scoped_ptr<RequestParams> request_params, CertNetFetcherImpl* parent); + ~Job() override; + + // Cancels the job and all requests attached to it. No callbacks will be + // invoked following cancellation. + void Cancel(); + + const RequestParams& request_params() const { return *request_params_; } + + // Create a request and attaches it to the job. When the job completes it will + // notify the request of completion through OnJobCompleted. Note that the Job + // does NOT own the request. + scoped_ptr<Request> CreateRequest(const FetchCallback& callback); + + // Removes |request| from the job. + void DetachRequest(RequestImpl* request); + + // Creates and starts a URLRequest for the job. After the request has + // completed, OnJobCompleted() will be invoked and all the registered requests + // notified of completion. + void StartURLRequest(URLRequestContext* context); + + private: + // The pointers in RequestList are not owned by the Job. + using RequestList = base::LinkedList<RequestImpl>; + + // Implementation of URLRequest::Delegate + void OnReceivedRedirect(URLRequest* request, + const RedirectInfo& redirect_info, + bool* defer_redirect) override; + void OnResponseStarted(URLRequest* request) override; + void OnReadCompleted(URLRequest* request, int bytes_read) override; + + // Clears the URLRequest and timer. Helper for doing work common to + // cancellation and job completion. + void Stop(); + + // Reads as much data as available from |request|. + void ReadBody(URLRequest* request); + + // Helper to copy the partial bytes read from the read IOBuffer to an + // aggregated buffer. + bool ConsumeBytesRead(URLRequest* request, int num_bytes); + + // Called once the job has exceeded its deadline. + void OnTimeout(); + + // Called when the URLRequest has completed (either success or failure). + void OnUrlRequestCompleted(URLRequest* request); + + // Called when the Job has completed. The job may finish in response to a + // timeout, an invalid URL, or the URLRequest completing. By the time this + // method is called, the response variables have been assigned + // (result_net_error_ and response_body_). + void OnJobCompleted(); + + // The requests attached to this job. + RequestList requests_; + + // The input parameters for starting a URLRequest. + scoped_ptr<RequestParams> request_params_; + + // The URLRequest response information. + std::vector<uint8_t> response_body_; + Error result_net_error_; + + scoped_ptr<URLRequest> url_request_; + scoped_refptr<IOBuffer> read_buffer_; + + // Used to timeout the job when the URLRequest takes too long. This timer is + // also used for notifying a failure to start the URLRequest. + base::OneShotTimer<Job> timer_; + + // Non-owned pointer to the CertNetFetcherImpl that created this job. + CertNetFetcherImpl* parent_; + + DISALLOW_COPY_AND_ASSIGN(Job); +}; + +CertNetFetcherImpl::RequestImpl::~RequestImpl() { + if (job_) + job_->DetachRequest(this); +} + +CertNetFetcherImpl::Job::Job(scoped_ptr<RequestParams> request_params, + CertNetFetcherImpl* parent) + : request_params_(request_params.Pass()), + result_net_error_(ERR_IO_PENDING), + parent_(parent) { +} + +CertNetFetcherImpl::Job::~Job() { + Cancel(); +} + +void CertNetFetcherImpl::Job::Cancel() { + parent_ = nullptr; + + // Notify each request of cancellation and remove it from the list. + for (base::LinkNode<RequestImpl>* current = requests_.head(); + current != requests_.end();) { + base::LinkNode<RequestImpl>* next = current->next(); + current->value()->OnJobCancelled(this); + current->RemoveFromList(); + current = next; + } + + DCHECK(requests_.empty()); + + Stop(); +} + +scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Job::CreateRequest( + const FetchCallback& callback) { + scoped_ptr<RequestImpl> request(new RequestImpl(this, callback)); + requests_.Append(request.get()); + return request.Pass(); +} + +void CertNetFetcherImpl::Job::DetachRequest(RequestImpl* request) { + scoped_ptr<Job> delete_this; + + request->RemoveFromList(); + + // If there are no longer any requests attached to the job then + // cancel and delete it. + if (requests_.empty()) + delete_this = parent_->RemoveJob(this); +} + +void CertNetFetcherImpl::Job::StartURLRequest(URLRequestContext* context) { + Error error = CanFetchUrl(request_params_->url); + if (error != OK) { + result_net_error_ = error; + // The CertNetFetcher's API contract is that requests always complete + // asynchronously. Use the timer class so the task is easily cancelled. + timer_.Start(FROM_HERE, base::TimeDelta(), this, &Job::OnJobCompleted); + return; + } + + // Start the URLRequest. + read_buffer_ = new IOBuffer(kReadBufferSizeInBytes); + url_request_ = + context->CreateRequest(request_params_->url, DEFAULT_PRIORITY, this); + if (request_params_->http_method == HTTP_METHOD_POST) + url_request_->set_method("POST"); + url_request_->SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES | + LOAD_DO_NOT_SEND_COOKIES); + url_request_->Start(); + + // Start a timer to limit how long the job runs for. + if (request_params_->timeout > base::TimeDelta()) + timer_.Start(FROM_HERE, request_params_->timeout, this, &Job::OnTimeout); +} + +void CertNetFetcherImpl::Job::OnReceivedRedirect( + URLRequest* request, + const RedirectInfo& redirect_info, + bool* defer_redirect) { + DCHECK_EQ(url_request_.get(), request); + + // Ensure that the new URL matches the policy. + Error error = CanFetchUrl(redirect_info.new_url); + if (error != OK) { + request->CancelWithError(error); + OnUrlRequestCompleted(request); + return; + } +} + +void CertNetFetcherImpl::Job::OnResponseStarted(URLRequest* request) { + DCHECK_EQ(url_request_.get(), request); + + if (!request->status().is_success()) { + OnUrlRequestCompleted(request); + return; + } + + if (request->GetResponseCode() != 200) { + // TODO(eroman): Use a more specific error code. + request->CancelWithError(ERR_FAILED); + OnUrlRequestCompleted(request); + return; + } + + ReadBody(request); +} + +void CertNetFetcherImpl::Job::OnReadCompleted(URLRequest* request, + int bytes_read) { + DCHECK_EQ(url_request_.get(), request); + + // Keep reading the response body. + if (ConsumeBytesRead(request, bytes_read)) + ReadBody(request); +} + +void CertNetFetcherImpl::Job::Stop() { + timer_.Stop(); + url_request_.reset(); +} + +void CertNetFetcherImpl::Job::ReadBody(URLRequest* request) { + // Read as many bytes as are available synchronously. + int num_bytes; + while ( + request->Read(read_buffer_.get(), kReadBufferSizeInBytes, &num_bytes)) { + if (!ConsumeBytesRead(request, num_bytes)) + return; + } + + // Check whether the read failed synchronously. + if (!request->status().is_io_pending()) + OnUrlRequestCompleted(request); + return; +} + +bool CertNetFetcherImpl::Job::ConsumeBytesRead(URLRequest* request, + int num_bytes) { + if (num_bytes <= 0) { + // Error while reading, or EOF. + OnUrlRequestCompleted(request); + return false; + } + + // Enforce maximum size bound. + if (num_bytes + response_body_.size() > request_params_->max_response_bytes) { + request->CancelWithError(ERR_FILE_TOO_BIG); + OnUrlRequestCompleted(request); + return false; + } + + // Append the data to |response_body_|. + response_body_.reserve(num_bytes); + response_body_.insert(response_body_.end(), read_buffer_->data(), + read_buffer_->data() + num_bytes); + return true; +} + +void CertNetFetcherImpl::Job::OnTimeout() { + result_net_error_ = ERR_TIMED_OUT; + url_request_->CancelWithError(result_net_error_); + OnJobCompleted(); +} + +void CertNetFetcherImpl::Job::OnUrlRequestCompleted(URLRequest* request) { + DCHECK_EQ(request, url_request_.get()); + + if (request->status().is_success()) + result_net_error_ = OK; + else + result_net_error_ = static_cast<Error>(request->status().error()); + + OnJobCompleted(); +} + +void CertNetFetcherImpl::Job::OnJobCompleted() { + // Stop the timer and clear the URLRequest. + Stop(); + + // Invoking the callbacks is subtle as state may be mutated while iterating + // through the callbacks: + // + // * The parent CertNetFetcherImpl may be deleted + // * Requests in this job may be cancelled + + scoped_ptr<Job> delete_this = parent_->RemoveJob(this); + parent_->SetCurrentlyCompletingJob(this); + + while (!requests_.empty()) { + base::LinkNode<RequestImpl>* request = requests_.head(); + request->RemoveFromList(); + request->value()->OnJobCompleted(this, result_net_error_, response_body_); + } + + if (parent_) + parent_->ClearCurrentlyCompletingJob(this); +} + +CertNetFetcherImpl::CertNetFetcherImpl(URLRequestContext* context) + : currently_completing_job_(nullptr), context_(context) { +} + +CertNetFetcherImpl::~CertNetFetcherImpl() { + STLDeleteElements(&jobs_); + + // The CertNetFetcherImpl was destroyed in a FetchCallback. Detach all + // remaining requests from the job so no further callbacks are called. + if (currently_completing_job_) + currently_completing_job_->Cancel(); +} + +scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCaIssuers( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) { + scoped_ptr<RequestParams> request_params(new RequestParams); + + request_params->url = url; + request_params->http_method = HTTP_METHOD_GET; + request_params->timeout = GetTimeout(timeout_milliseconds); + request_params->max_response_bytes = + GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); + + return Fetch(request_params.Pass(), callback); +} + +scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchCrl( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) { + scoped_ptr<RequestParams> request_params(new RequestParams); + + request_params->url = url; + request_params->http_method = HTTP_METHOD_GET; + request_params->timeout = GetTimeout(timeout_milliseconds); + request_params->max_response_bytes = + GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForCrl); + + return Fetch(request_params.Pass(), callback); +} + +scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::FetchOcsp( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) { + scoped_ptr<RequestParams> request_params(new RequestParams); + + request_params->url = url; + request_params->http_method = HTTP_METHOD_GET; + request_params->timeout = GetTimeout(timeout_milliseconds); + request_params->max_response_bytes = + GetMaxResponseBytes(max_response_bytes, kMaxResponseSizeInBytesForAia); + + return Fetch(request_params.Pass(), callback); +} + +bool CertNetFetcherImpl::JobComparator::operator()(const Job* job1, + const Job* job2) const { + return job1->request_params() < job2->request_params(); +} + +scoped_ptr<CertNetFetcher::Request> CertNetFetcherImpl::Fetch( + scoped_ptr<RequestParams> request_params, + const FetchCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // If there is an in-progress job that matches the request parameters use it. + // Otherwise start a new job. + Job* job = FindJob(*request_params); + + if (!job) { + job = new Job(request_params.Pass(), this); + jobs_.insert(job); + job->StartURLRequest(context_); + } + + return job->CreateRequest(callback); +} + +struct CertNetFetcherImpl::JobToRequestParamsComparator { + bool operator()(const Job* job, + const CertNetFetcherImpl::RequestParams& value) const { + return job->request_params() < value; + } +}; + +CertNetFetcherImpl::Job* CertNetFetcherImpl::FindJob( + const RequestParams& params) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // The JobSet is kept in sorted order so items can be found using binary + // search. + JobSet::iterator it = std::lower_bound(jobs_.begin(), jobs_.end(), params, + JobToRequestParamsComparator()); + if (it != jobs_.end() && !(params < (*it)->request_params())) + return *it; + return nullptr; +} + +scoped_ptr<CertNetFetcherImpl::Job> CertNetFetcherImpl::RemoveJob(Job* job) { + DCHECK(thread_checker_.CalledOnValidThread()); + bool erased_job = jobs_.erase(job) == 1; + DCHECK(erased_job); + return make_scoped_ptr(job); +} + +void CertNetFetcherImpl::SetCurrentlyCompletingJob(Job* job) { + DCHECK(!currently_completing_job_); + DCHECK(job); + currently_completing_job_ = job; +} + +void CertNetFetcherImpl::ClearCurrentlyCompletingJob(Job* job) { + DCHECK_EQ(currently_completing_job_, job); + currently_completing_job_ = nullptr; +} + +} // namespace net
diff --git a/net/cert_net/cert_net_fetcher_impl.h b/net/cert_net/cert_net_fetcher_impl.h new file mode 100644 index 0000000..692647a --- /dev/null +++ b/net/cert_net/cert_net_fetcher_impl.h
@@ -0,0 +1,107 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CERT_NET_CERT_NET_FETCHER_H_ +#define NET_CERT_NET_CERT_NET_FETCHER_H_ + +#include <set> + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" +#include "net/base/net_errors.h" +#include "net/base/net_export.h" +#include "net/cert/cert_net_fetcher.h" + +namespace net { + +class URLRequestContext; + +// CertNetFetcherImpl is an implementation of CertNetFetcher that uses the +// network stack. +// +// For more details refer to the documentation for the interface. +class NET_EXPORT CertNetFetcherImpl : public CertNetFetcher { + public: + // Initializes CertNetFetcherImpl using the specified URLRequestContext for + // issuing requests. |context| must remain valid for the entire lifetime of + // the CertNetFetcherImpl. + explicit CertNetFetcherImpl(URLRequestContext* context); + + // Deletion implicitly cancels any outstanding requests. + ~CertNetFetcherImpl() override; + + WARN_UNUSED_RESULT scoped_ptr<Request> FetchCaIssuers( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) override; + + WARN_UNUSED_RESULT scoped_ptr<Request> FetchCrl( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) override; + + WARN_UNUSED_RESULT scoped_ptr<Request> FetchOcsp( + const GURL& url, + int timeout_milliseconds, + int max_response_bytes, + const FetchCallback& callback) override; + + private: + class RequestImpl; + class Job; + struct JobToRequestParamsComparator; + struct RequestParams; + + struct JobComparator { + bool operator()(const Job* job1, const Job* job2) const; + }; + + // Owns the jobs. + using JobSet = std::set<Job*, JobComparator>; + + // Starts an asynchronous request to fetch the given URL. On completion + // |callback| will be invoked. + // + // Completion of the request will never occur synchronously. In other words it + // is guaranteed that |callback| will only be invoked once the Fetch*() method + // has returned. + WARN_UNUSED_RESULT scoped_ptr<Request> Fetch( + scoped_ptr<RequestParams> request_params, + const FetchCallback& callback); + + // Finds a job with a matching RequestPararms or returns nullptr if there was + // no match. + Job* FindJob(const RequestParams& params); + + // Removes |job| from the in progress jobs and transfers ownership to the + // caller. + scoped_ptr<Job> RemoveJob(Job* job); + + // Indicates which Job is currently executing inside of OnJobCompleted(). + void SetCurrentlyCompletingJob(Job* job); + void ClearCurrentlyCompletingJob(Job* job); + + // The in-progress jobs. This set does not contain the job which is actively + // invoking callbacks (OnJobCompleted). Instead that is tracked by + // |currently_completing_job_|. + JobSet jobs_; + + // The Job that is currently executing OnJobCompleted(). There can be at most + // one such job. This pointer is not owned. + Job* currently_completing_job_; + + // Not owned. CertNetFetcherImpl must outlive the URLRequestContext. + URLRequestContext* context_; + + base::ThreadChecker thread_checker_; + + DISALLOW_COPY_AND_ASSIGN(CertNetFetcherImpl); +}; + +} // namespace net + +#endif // NET_CERT_NET_CERT_NET_FETCHER_H_
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc new file mode 100644 index 0000000..2003a41 --- /dev/null +++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -0,0 +1,729 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert_net/cert_net_fetcher_impl.h" + +#include <string> + +#include "base/compiler_specific.h" +#include "base/run_loop.h" +#include "net/cert/mock_cert_verifier.h" +#include "net/dns/mock_host_resolver.h" +#include "net/http/http_server_properties_impl.h" +#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +// TODO(eroman): Test that cookies aren't sent. + +using base::ASCIIToUTF16; + +namespace net { + +namespace { + +const base::FilePath::CharType kDocRoot[] = + FILE_PATH_LITERAL("net/data/cert_net_fetcher_impl_unittest"); + +// A non-mock URLRequestContext which can access http:// urls. +class RequestContext : public URLRequestContext { + public: + RequestContext() : storage_(this) { + ProxyConfig no_proxy; + storage_.set_host_resolver(scoped_ptr<HostResolver>(new MockHostResolver)); + storage_.set_cert_verifier(new MockCertVerifier); + storage_.set_transport_security_state(new TransportSecurityState); + storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy)); + storage_.set_ssl_config_service(new SSLConfigServiceDefaults); + storage_.set_http_server_properties( + scoped_ptr<HttpServerProperties>(new HttpServerPropertiesImpl())); + + HttpNetworkSession::Params params; + params.host_resolver = host_resolver(); + params.cert_verifier = cert_verifier(); + params.transport_security_state = transport_security_state(); + params.proxy_service = proxy_service(); + params.ssl_config_service = ssl_config_service(); + params.http_server_properties = http_server_properties(); + scoped_refptr<HttpNetworkSession> network_session( + new HttpNetworkSession(params)); + storage_.set_http_transaction_factory(new HttpCache( + network_session.get(), HttpCache::DefaultBackend::InMemory(0))); + URLRequestJobFactoryImpl* job_factory = new URLRequestJobFactoryImpl(); + storage_.set_job_factory(job_factory); + } + + ~RequestContext() override { AssertNoURLRequests(); } + + private: + URLRequestContextStorage storage_; +}; + +class FetchResult { + public: + FetchResult(Error net_error, const std::vector<uint8_t>& response_body) + : net_error_(net_error), response_body_(response_body) {} + + void VerifySuccess(const std::string& expected_body) { + EXPECT_EQ(OK, net_error_); + EXPECT_EQ(expected_body, + std::string(response_body_.begin(), response_body_.end())); + } + + void VerifyFailure(Error expected_error) { + EXPECT_EQ(expected_error, net_error_); + EXPECT_EQ(0u, response_body_.size()); + } + + private: + const Error net_error_; + const std::vector<uint8_t> response_body_; +}; + +// Helper to synchronously wait for the fetch completion. This is similar to +// net's TestCompletionCallback, but built around FetchCallback. +class TestFetchCallback { + public: + TestFetchCallback() + : callback_(base::Bind(&TestFetchCallback::OnCallback, + base::Unretained(this))) {} + + const CertNetFetcher::FetchCallback& callback() const { return callback_; } + + scoped_ptr<FetchResult> WaitForResult() { + DCHECK(quit_closure_.is_null()); + while (!HasResult()) { + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + quit_closure_.Reset(); + } + return result_.Pass(); + } + + bool HasResult() const { return result_.get(); } + + // Sets an extra action (in addition to recording the result) that is run when + // the FetchCallback is invoked. + void set_extra_closure(const base::Closure& closure) { + extra_closure_ = closure; + } + + private: + void OnCallback(Error net_error, const std::vector<uint8_t>& response_body) { + DCHECK(!HasResult()); + result_.reset(new FetchResult(net_error, response_body)); + + if (!extra_closure_.is_null()) + extra_closure_.Run(); + + if (!quit_closure_.is_null()) + quit_closure_.Run(); + } + + CertNetFetcher::FetchCallback callback_; + scoped_ptr<FetchResult> result_; + base::Closure quit_closure_; + base::Closure extra_closure_; +}; + +} // namespace + +class CertNetFetcherImplTest : public PlatformTest { + public: + CertNetFetcherImplTest() + : test_server_(SpawnedTestServer::TYPE_HTTP, + net::SpawnedTestServer::kLocalhost, + base::FilePath(kDocRoot)) { + context_.set_network_delegate(&network_delegate_); + } + + protected: + SpawnedTestServer test_server_; + TestNetworkDelegate network_delegate_; + RequestContext context_; +}; + +// Helper to start an AIA fetch using default parameters. +WARN_UNUSED_RESULT scoped_ptr<CertNetFetcher::Request> StartRequest( + CertNetFetcher* fetcher, + const GURL& url, + const TestFetchCallback& callback) { + return fetcher->FetchCaIssuers(url, CertNetFetcher::DEFAULT, + CertNetFetcher::DEFAULT, callback.callback()); +} + +// Fetch a few unique URLs using GET in parallel. Each URL has a different body +// and Content-Type. +TEST_F(CertNetFetcherImplTest, ParallelFetchNoDuplicates) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + TestFetchCallback callback1; + TestFetchCallback callback2; + TestFetchCallback callback3; + + // Request a URL with Content-Type "application/pkix-cert" + GURL url1 = test_server_.GetURL("files/cert.crt"); + scoped_ptr<CertNetFetcher::Request> request1 = + StartRequest(&fetcher, url1, callback1); + + // Request a URL with Content-Type "application/pkix-crl" + GURL url2 = test_server_.GetURL("files/root.crl"); + scoped_ptr<CertNetFetcher::Request> request2 = + StartRequest(&fetcher, url2, callback2); + + // Request a URL with Content-Type "application/pkcs7-mime" + GURL url3 = test_server_.GetURL("files/certs.p7c"); + scoped_ptr<CertNetFetcher::Request> request3 = + StartRequest(&fetcher, url3, callback3); + + // Wait for all of the requests to complete. + scoped_ptr<FetchResult> result1 = callback1.WaitForResult(); + scoped_ptr<FetchResult> result2 = callback2.WaitForResult(); + scoped_ptr<FetchResult> result3 = callback3.WaitForResult(); + + // Verify the fetch results. + result1->VerifySuccess("-cert.crt-\n"); + result2->VerifySuccess("-root.crl-\n"); + result3->VerifySuccess("-certs.p7c-\n"); + + EXPECT_EQ(3, network_delegate_.created_requests()); +} + +// Fetch a caIssuers URL which has an unexpected extension and Content-Type. +// The extension is .txt and the Content-Type is text/plain. Despite being +// unusual this succeeds as the extension and Content-Type are not required to +// be meaningful. +TEST_F(CertNetFetcherImplTest, ContentTypeDoesntMatter) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + TestFetchCallback callback; + GURL url = test_server_.GetURL("files/foo.txt"); + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifySuccess("-foo.txt-\n"); +} + +// Fetch a URLs whose HTTP response code is not 200. These are considered +// failures. +TEST_F(CertNetFetcherImplTest, HttpStatusCode) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + // Response was HTTP status 404. + { + TestFetchCallback callback; + GURL url = test_server_.GetURL("files/404.html"); + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifyFailure(ERR_FAILED); + } + + // Response was HTTP status 500. + { + TestFetchCallback callback; + GURL url = test_server_.GetURL("files/500.html"); + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifyFailure(ERR_FAILED); + } +} + +// Fetching a URL with a Content-Disposition header should have no effect. +TEST_F(CertNetFetcherImplTest, ContentDisposition) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + TestFetchCallback callback; + GURL url = test_server_.GetURL("files/downloadable.js"); + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifySuccess("-downloadable.js-\n"); +} + +// Verifies that a cachable request will be served from the HTTP cache the +// second time it is requested. +TEST_F(CertNetFetcherImplTest, Cache) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + // Fetch a URL whose HTTP headers make it cacheable for 1 hour. + GURL url(test_server_.GetURL("files/cacheable_1hr.crt")); + { + TestFetchCallback callback; + + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifySuccess("-cacheable_1hr.crt-\n"); + } + + EXPECT_EQ(1, network_delegate_.created_requests()); + + // Kill the HTTP server. + ASSERT_TRUE(test_server_.Stop()); + + // Fetch again -- will fail unless served from cache. + { + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifySuccess("-cacheable_1hr.crt-\n"); + } + + EXPECT_EQ(2, network_delegate_.created_requests()); +} + +// Verify that the maximum response body constraints are enforced by fetching a +// resource that is larger than the limit. +TEST_F(CertNetFetcherImplTest, TooLarge) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + // This file has a response body 12 bytes long. So setting the maximum to 11 + // bytes will cause it to fail. + GURL url(test_server_.GetURL("files/certs.p7c")); + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = fetcher.FetchCaIssuers( + url, CertNetFetcher::DEFAULT, 11, callback.callback()); + + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifyFailure(ERR_FILE_TOO_BIG); +} + +// Set the timeout to 10 milliseconds, and try fetching a URL that takes 5 +// seconds to complete. It should fail due to a timeout. +TEST_F(CertNetFetcherImplTest, Hang) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url(test_server_.GetURL("slow/certs.p7c?5")); + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = fetcher.FetchCaIssuers( + url, 10, CertNetFetcher::DEFAULT, callback.callback()); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifyFailure(ERR_TIMED_OUT); +} + +// Verify that if a response is gzip-encoded it gets inflated before being +// returned to the caller. +TEST_F(CertNetFetcherImplTest, Gzip) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url(test_server_.GetURL("files/gzipped_crl")); + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifySuccess("-gzipped_crl-\n"); +} + +// Try fetching an unsupported URL scheme (https). +TEST_F(CertNetFetcherImplTest, HttpsNotAllowed) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url("https://foopy/foo.crt"); + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + // Should NOT complete synchronously despite being a test that could be done + // immediately. + EXPECT_FALSE(callback.HasResult()); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifyFailure(ERR_DISALLOWED_URL_SCHEME); + + // No request was created because the URL scheme was unsupported. + EXPECT_EQ(0, network_delegate_.created_requests()); +} + +// Try fetching a URL which redirects to https. +TEST_F(CertNetFetcherImplTest, RedirectToHttpsNotAllowed) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url(test_server_.GetURL("files/redirect_https")); + TestFetchCallback callback; + + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + scoped_ptr<FetchResult> result = callback.WaitForResult(); + result->VerifyFailure(ERR_DISALLOWED_URL_SCHEME); + + EXPECT_EQ(1, network_delegate_.created_requests()); +} + +// Try fetching an unsupported URL scheme (https) and then immediately +// cancelling. This is a bit special because this codepath needs to post a task. +TEST_F(CertNetFetcherImplTest, CancelHttpsNotAllowed) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url("https://foopy/foo.crt"); + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(&fetcher, url, callback); + + // Cancel the request. + request.reset(); + + // Spin the message loop to increase chance of catching a bug. + base::RunLoop().RunUntilIdle(); + + // Should NOT complete synchronously despite being a test that could be done + // immediately. + EXPECT_FALSE(callback.HasResult()); + + EXPECT_EQ(0, network_delegate_.created_requests()); +} + +// Start a few requests, and cancel one of them before running the message loop +// again. +TEST_F(CertNetFetcherImplTest, CancelBeforeRunningMessageLoop) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + TestFetchCallback callback1; + TestFetchCallback callback2; + TestFetchCallback callback3; + + GURL url1 = test_server_.GetURL("files/cert.crt"); + scoped_ptr<CertNetFetcher::Request> request1 = + StartRequest(&fetcher, url1, callback1); + + GURL url2 = test_server_.GetURL("files/root.crl"); + scoped_ptr<CertNetFetcher::Request> request2 = + StartRequest(&fetcher, url2, callback2); + + GURL url3 = test_server_.GetURL("files/certs.p7c"); + + scoped_ptr<CertNetFetcher::Request> request3 = + StartRequest(&fetcher, url3, callback3); + + EXPECT_EQ(3, network_delegate_.created_requests()); + EXPECT_FALSE(callback1.HasResult()); + EXPECT_FALSE(callback2.HasResult()); + EXPECT_FALSE(callback3.HasResult()); + + // Cancel the second request. + request2.reset(); + + // Wait for the non-cancelled requests to complete. + scoped_ptr<FetchResult> result1 = callback1.WaitForResult(); + scoped_ptr<FetchResult> result3 = callback3.WaitForResult(); + + // Verify the fetch results. + result1->VerifySuccess("-cert.crt-\n"); + result3->VerifySuccess("-certs.p7c-\n"); + + EXPECT_FALSE(callback2.HasResult()); +} + +// Start several requests, and cancel one of them after the first has completed. +// NOTE: The python test server is single threaded and can only service one +// request at a time. After a socket is opened by the server it waits for it to +// be completed, and any subsequent request will hang until the first socket is +// closed. +// Cancelling the first request can therefore be problematic, since if +// cancellation is done after the socket is opened but before reading/writing, +// then the socket is re-cycled and things will be stalled until the cleanup +// timer (10 seconds) closes it. +// To work around this, the last request is cancelled, and hope that the +// requests are given opened sockets in a FIFO order. +// TODO(eroman): Make this more robust. +TEST_F(CertNetFetcherImplTest, CancelAfterRunningMessageLoop) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + TestFetchCallback callback1; + TestFetchCallback callback2; + TestFetchCallback callback3; + + GURL url1 = test_server_.GetURL("files/cert.crt"); + + scoped_ptr<CertNetFetcher::Request> request1 = + StartRequest(&fetcher, url1, callback1); + + GURL url2 = test_server_.GetURL("files/certs.p7c"); + scoped_ptr<CertNetFetcher::Request> request2 = + StartRequest(&fetcher, url2, callback2); + + GURL url3("ftp://www.not.supported.com/foo"); + scoped_ptr<CertNetFetcher::Request> request3 = + StartRequest(&fetcher, url3, callback3); + + EXPECT_FALSE(callback1.HasResult()); + EXPECT_FALSE(callback2.HasResult()); + EXPECT_FALSE(callback3.HasResult()); + + // Wait for the ftp request to complete (it should complete right away since + // it doesn't even try to connect to the server). + scoped_ptr<FetchResult> result3 = callback3.WaitForResult(); + result3->VerifyFailure(ERR_DISALLOWED_URL_SCHEME); + + // Cancel the second outstanding request. + request2.reset(); + + // Wait for the first request to complete. + scoped_ptr<FetchResult> result2 = callback1.WaitForResult(); + + // Verify the fetch results. + result2->VerifySuccess("-cert.crt-\n"); +} + +// Delete a CertNetFetcherImpl with outstanding requests on it. +TEST_F(CertNetFetcherImplTest, DeleteCancels) { + ASSERT_TRUE(test_server_.Start()); + + scoped_ptr<CertNetFetcherImpl> fetcher(new CertNetFetcherImpl(&context_)); + + GURL url(test_server_.GetURL("slow/certs.p7c?20")); + TestFetchCallback callback; + scoped_ptr<CertNetFetcher::Request> request = + StartRequest(fetcher.get(), url, callback); + + // Destroy the fetcher before the outstanding request. + fetcher.reset(); +} + +// Fetch the same URLs in parallel and verify that only 1 request is made per +// URL. +TEST_F(CertNetFetcherImplTest, ParallelFetchDuplicates) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url1 = test_server_.GetURL("files/cert.crt"); + GURL url2 = test_server_.GetURL("files/root.crl"); + + // Issue 3 requests for url1, and 3 requests for url2 + TestFetchCallback callback1; + scoped_ptr<CertNetFetcher::Request> request1 = + StartRequest(&fetcher, url1, callback1); + + TestFetchCallback callback2; + scoped_ptr<CertNetFetcher::Request> request2 = + StartRequest(&fetcher, url2, callback2); + + TestFetchCallback callback3; + scoped_ptr<CertNetFetcher::Request> request3 = + StartRequest(&fetcher, url1, callback3); + + TestFetchCallback callback4; + scoped_ptr<CertNetFetcher::Request> request4 = + StartRequest(&fetcher, url2, callback4); + + TestFetchCallback callback5; + scoped_ptr<CertNetFetcher::Request> request5 = + StartRequest(&fetcher, url2, callback5); + + TestFetchCallback callback6; + scoped_ptr<CertNetFetcher::Request> request6 = + StartRequest(&fetcher, url1, callback6); + + // Cancel all but one of the requests for url1. + request1.reset(); + request3.reset(); + + // Wait for the remaining requests to finish. + scoped_ptr<FetchResult> result2 = callback2.WaitForResult(); + scoped_ptr<FetchResult> result4 = callback4.WaitForResult(); + scoped_ptr<FetchResult> result5 = callback5.WaitForResult(); + scoped_ptr<FetchResult> result6 = callback6.WaitForResult(); + + // Verify that none of the cancelled requests for url1 completed (since they + // were cancelled). + EXPECT_FALSE(callback1.HasResult()); + EXPECT_FALSE(callback3.HasResult()); + + // Verify the fetch results. + result2->VerifySuccess("-root.crl-\n"); + result4->VerifySuccess("-root.crl-\n"); + result5->VerifySuccess("-root.crl-\n"); + result6->VerifySuccess("-cert.crt-\n"); + + // Verify that only 2 URLRequests were started even though 6 requests were + // issued. + EXPECT_EQ(2, network_delegate_.created_requests()); +} + +// Cancel a request and then start another one for the same URL. +TEST_F(CertNetFetcherImplTest, CancelThenStart) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + TestFetchCallback callback1; + TestFetchCallback callback2; + TestFetchCallback callback3; + + GURL url = test_server_.GetURL("files/cert.crt"); + + scoped_ptr<CertNetFetcher::Request> request1 = + StartRequest(&fetcher, url, callback1); + request1.reset(); + + scoped_ptr<CertNetFetcher::Request> request2 = + StartRequest(&fetcher, url, callback2); + + scoped_ptr<CertNetFetcher::Request> request3 = + StartRequest(&fetcher, url, callback3); + request3.reset(); + + // All but |request2| were canceled. + scoped_ptr<FetchResult> result = callback2.WaitForResult(); + + result->VerifySuccess("-cert.crt-\n"); + + EXPECT_FALSE(callback1.HasResult()); + EXPECT_FALSE(callback3.HasResult()); + + // One URLRequest that was cancelled, then another right afterwards. + EXPECT_EQ(2, network_delegate_.created_requests()); +} + +// Start duplicate requests and then cancel all of them. +TEST_F(CertNetFetcherImplTest, CancelAll) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + TestFetchCallback callback[3]; + scoped_ptr<CertNetFetcher::Request> request[3]; + + GURL url = test_server_.GetURL("files/cert.crt"); + + for (size_t i = 0; i < arraysize(callback); ++i) { + request[i] = StartRequest(&fetcher, url, callback[i]); + } + + // Cancel all the requests. + for (size_t i = 0; i < arraysize(request); ++i) + request[i].reset(); + + EXPECT_EQ(1, network_delegate_.created_requests()); + + for (size_t i = 0; i < arraysize(request); ++i) + EXPECT_FALSE(callback[i].HasResult()); +} + +void DeleteCertNetFetcher(CertNetFetcher* fetcher) { + delete fetcher; +} + +// Delete the CertNetFetcherImpl within a request callback. +TEST_F(CertNetFetcherImplTest, DeleteWithinCallback) { + ASSERT_TRUE(test_server_.Start()); + + // Deleted by callback2. + CertNetFetcher* fetcher = new CertNetFetcherImpl(&context_); + + GURL url = test_server_.GetURL("files/cert.crt"); + + TestFetchCallback callback[4]; + scoped_ptr<CertNetFetcher::Request> reqs[4]; + callback[1].set_extra_closure(base::Bind(DeleteCertNetFetcher, fetcher)); + + for (size_t i = 0; i < arraysize(callback); ++i) + reqs[i] = StartRequest(fetcher, url, callback[i]); + + EXPECT_EQ(1, network_delegate_.created_requests()); + + callback[1].WaitForResult(); + + // Assume requests for the same URL are executed in FIFO order. + EXPECT_TRUE(callback[0].HasResult()); + EXPECT_FALSE(callback[2].HasResult()); + EXPECT_FALSE(callback[3].HasResult()); +} + +void FetchRequest(CertNetFetcher* fetcher, + const GURL& url, + TestFetchCallback* callback, + scoped_ptr<CertNetFetcher::Request>* request) { + *request = StartRequest(fetcher, url, *callback); +} + +// Make a request during callback for the same URL. +TEST_F(CertNetFetcherImplTest, FetchWithinCallback) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url = test_server_.GetURL("files/cert.crt"); + + TestFetchCallback callback[5]; + scoped_ptr<CertNetFetcher::Request> req[5]; + callback[1].set_extra_closure( + base::Bind(FetchRequest, &fetcher, url, &callback[4], &req[4])); + + for (size_t i = 0; i < arraysize(callback) - 1; ++i) + req[i] = StartRequest(&fetcher, url, callback[i]); + + EXPECT_EQ(1, network_delegate_.created_requests()); + + for (size_t i = 0; i < arraysize(callback); ++i) { + scoped_ptr<FetchResult> result = callback[i].WaitForResult(); + result->VerifySuccess("-cert.crt-\n"); + } + + // The fetch started within a callback should have started a new request + // rather than attaching to the current job. + EXPECT_EQ(2, network_delegate_.created_requests()); +} + +void CancelRequest(scoped_ptr<CertNetFetcher::Request>* request) { + request->reset(); +} + +// Cancel a request while executing a callback for the same job. +TEST_F(CertNetFetcherImplTest, CancelWithinCallback) { + ASSERT_TRUE(test_server_.Start()); + + CertNetFetcherImpl fetcher(&context_); + + GURL url = test_server_.GetURL("files/cert.crt"); + + TestFetchCallback callback[4]; + scoped_ptr<CertNetFetcher::Request> request[4]; + + for (size_t i = 0; i < arraysize(callback); ++i) + request[i] = StartRequest(&fetcher, url, callback[i]); + + // Cancel request[2] when the callback for request[1] runs. + callback[1].set_extra_closure(base::Bind(CancelRequest, &request[2])); + + EXPECT_EQ(1, network_delegate_.created_requests()); + + for (size_t i = 0; i < arraysize(request); ++i) { + if (i == 2) + continue; + + scoped_ptr<FetchResult> result = callback[i].WaitForResult(); + result->VerifySuccess("-cert.crt-\n"); + } + + // request[2] was cancelled. + EXPECT_FALSE(callback[2].HasResult()); +} + +} // namespace net
diff --git a/net/ocsp/nss_ocsp.cc b/net/cert_net/nss_ocsp.cc similarity index 99% rename from net/ocsp/nss_ocsp.cc rename to net/cert_net/nss_ocsp.cc index 811b82d..290c3192 100644 --- a/net/ocsp/nss_ocsp.cc +++ b/net/cert_net/nss_ocsp.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/ocsp/nss_ocsp.h" +#include "net/cert_net/nss_ocsp.h" #include <certt.h> #include <certdb.h>
diff --git a/net/ocsp/nss_ocsp.h b/net/cert_net/nss_ocsp.h similarity index 92% rename from net/ocsp/nss_ocsp.h rename to net/cert_net/nss_ocsp.h index fd840056..a422cb22 100644 --- a/net/ocsp/nss_ocsp.h +++ b/net/cert_net/nss_ocsp.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NET_OCSP_NSS_OCSP_H_ -#define NET_OCSP_NSS_OCSP_H_ +#ifndef NET_CERT_NET_NSS_OCSP_H_ +#define NET_CERT_NET_NSS_OCSP_H_ #include "net/base/net_export.h" @@ -36,4 +36,4 @@ } // namespace net -#endif // NET_OCSP_NSS_OCSP_H_ +#endif // NET_CERT_NET_NSS_OCSP_H_
diff --git a/net/ocsp/nss_ocsp_unittest.cc b/net/cert_net/nss_ocsp_unittest.cc similarity index 98% rename from net/ocsp/nss_ocsp_unittest.cc rename to net/cert_net/nss_ocsp_unittest.cc index 745741e..155bcb2 100644 --- a/net/ocsp/nss_ocsp_unittest.cc +++ b/net/cert_net/nss_ocsp_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/ocsp/nss_ocsp.h" +#include "net/cert_net/nss_ocsp.h" #include <string>
diff --git a/net/data/cert_net_fetcher_impl_unittest/404.html b/net/data/cert_net_fetcher_impl_unittest/404.html new file mode 100644 index 0000000..7469b535 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/404.html
@@ -0,0 +1 @@ +-404.html-
diff --git a/net/data/cert_net_fetcher_impl_unittest/404.html.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/404.html.mock-http-headers new file mode 100644 index 0000000..b2eb12c --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/404.html.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 404 OK +Content-Type: text/html
diff --git a/net/data/cert_net_fetcher_impl_unittest/500.html b/net/data/cert_net_fetcher_impl_unittest/500.html new file mode 100644 index 0000000..c5a13a0 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/500.html
@@ -0,0 +1 @@ +-500.html-
diff --git a/net/data/cert_net_fetcher_impl_unittest/500.html.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/500.html.mock-http-headers new file mode 100644 index 0000000..29aec5b2 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/500.html.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 500 OK +Content-Type: text/html
diff --git a/net/data/cert_net_fetcher_impl_unittest/cacheable_1hr.crt b/net/data/cert_net_fetcher_impl_unittest/cacheable_1hr.crt new file mode 100644 index 0000000..d4b31849 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/cacheable_1hr.crt
@@ -0,0 +1 @@ +-cacheable_1hr.crt-
diff --git a/net/data/cert_net_fetcher_impl_unittest/cacheable_1hr.crt.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/cacheable_1hr.crt.mock-http-headers new file mode 100644 index 0000000..0b45d9a --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/cacheable_1hr.crt.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Type: application/pkix-cert +Cache-Control: public, max-age=3600
diff --git a/net/data/cert_net_fetcher_impl_unittest/cert.crt b/net/data/cert_net_fetcher_impl_unittest/cert.crt new file mode 100644 index 0000000..3c046339 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/cert.crt
@@ -0,0 +1 @@ +-cert.crt-
diff --git a/net/data/cert_net_fetcher_impl_unittest/cert.crt.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/cert.crt.mock-http-headers new file mode 100644 index 0000000..9fd04d6 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/cert.crt.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Type: application/pkix-cert
diff --git a/net/data/cert_net_fetcher_impl_unittest/certs.p7c b/net/data/cert_net_fetcher_impl_unittest/certs.p7c new file mode 100644 index 0000000..edee1da --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/certs.p7c
@@ -0,0 +1 @@ +-certs.p7c-
diff --git a/net/data/cert_net_fetcher_impl_unittest/certs.p7c.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/certs.p7c.mock-http-headers new file mode 100644 index 0000000..ac4f6679 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/certs.p7c.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Type: application/pkcs7-mime
diff --git a/net/data/cert_net_fetcher_impl_unittest/downloadable.js b/net/data/cert_net_fetcher_impl_unittest/downloadable.js new file mode 100644 index 0000000..5c291b0 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/downloadable.js
@@ -0,0 +1 @@ +-downloadable.js-
diff --git a/net/data/cert_net_fetcher_impl_unittest/downloadable.js.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/downloadable.js.mock-http-headers new file mode 100644 index 0000000..a05c710 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/downloadable.js.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Type: text/javascript +Content-Disposition: attachment; filename="download-me.exe"
diff --git a/net/data/cert_net_fetcher_impl_unittest/foo.txt b/net/data/cert_net_fetcher_impl_unittest/foo.txt new file mode 100644 index 0000000..71c1bb86 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/foo.txt
@@ -0,0 +1 @@ +-foo.txt-
diff --git a/net/data/cert_net_fetcher_impl_unittest/foo.txt.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/foo.txt.mock-http-headers new file mode 100644 index 0000000..5c695b91 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/foo.txt.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Type: text/plain
diff --git a/net/data/cert_net_fetcher_impl_unittest/gzipped_crl b/net/data/cert_net_fetcher_impl_unittest/gzipped_crl new file mode 100644 index 0000000..d3a2b70 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/gzipped_crl Binary files differ
diff --git a/net/data/cert_net_fetcher_impl_unittest/gzipped_crl.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/gzipped_crl.mock-http-headers new file mode 100644 index 0000000..5fa16aed --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/gzipped_crl.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Type: application/pkix-crl +Content-Encoding: gzip
diff --git a/net/data/cert_net_fetcher_impl_unittest/redirect_https b/net/data/cert_net_fetcher_impl_unittest/redirect_https new file mode 100644 index 0000000..d3e8d974 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/redirect_https
@@ -0,0 +1 @@ +-redirected_https-
diff --git a/net/data/cert_net_fetcher_impl_unittest/redirect_https.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/redirect_https.mock-http-headers new file mode 100644 index 0000000..dfe42e7 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/redirect_https.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 302 Found +Location: https://www.foo/
diff --git a/net/data/cert_net_fetcher_impl_unittest/root.crl b/net/data/cert_net_fetcher_impl_unittest/root.crl new file mode 100644 index 0000000..a384a90 --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/root.crl
@@ -0,0 +1 @@ +-root.crl-
diff --git a/net/data/cert_net_fetcher_impl_unittest/root.crl.mock-http-headers b/net/data/cert_net_fetcher_impl_unittest/root.crl.mock-http-headers new file mode 100644 index 0000000..d589c66c --- /dev/null +++ b/net/data/cert_net_fetcher_impl_unittest/root.crl.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Type: application/pkix-crl
diff --git a/net/data/ssl/certificates/localhost_cert.pem b/net/data/ssl/certificates/localhost_cert.pem new file mode 100644 index 0000000..273a9c4 --- /dev/null +++ b/net/data/ssl/certificates/localhost_cert.pem
@@ -0,0 +1,111 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQCvaqKl55EBl974 +UxivDfhGARaIX5OUIO9RVi98YYXMEoIGC9IcUtfFyMNzqyaR30HzslhsQrunl3J9 +voeZAU9zh/jr5kW/PKFL0DMeoKUEToDFCvZaLZoJljRZ8gZxPZ7+qBm/RancIMjm +mwce/v+rwh7k/gt1SbyhG7wD+8SzxC9ABYRwi9RbuKdfZ+KfpovU2uRPi8JYxSm2 +drgZCs4AEVFiIjvgkNv2rn93wx/blT0f4nse7oFboecSFT3U1Hu1P8MZP/tLEfhj +PWc/eitEiIKdBVVMMQcO1hQXpbLCTndVhmYOOd18+G/hkkuwynigtDKI8kQQGz64 +em09uCsDAgMBAAECggEBAJyRYjEQWfYBFuuwR4TfxCy/hdwc6r05FEIV2fZ7mQ+H +qXQ6EsRjEOIhCorwRVHH4rbgBVpDyfiRDYi8iY0AhWjKAVyUwMYrGJBxeV8p5X/N +jdPRsAbXUvihj4KEqklixcnoQmrdg/nNbWOfFaEN2yfz8N1U/ucl9G4cMhmgG3aS +94lppp5bqse61wVLKZUJVzBR7V0L8pgei7ZIJsI30k/gB+hqAiDlzL0veuTyhbP3 +wsr32bOCi8cBKro6wQkVIGWtkC7Rghz8VwfsR67Rxg+hsTPEJ34CFCl6TXctEItY +gEVwRgHdw3Oe/83xlzNfSkkkQ9CQDeL3kvhW0POjbbkCgYEA1Uish6WiLRVQpwnN +rSZNaLrH06Py20wpd2MKAp3p7JhsY1TO1IP1XPrq3899u8vNL6RjZ6fydspRLOOt +d9ZkzmOSz4R9J6HQSz3NAQrK2yHw/1RJ0W8IjVHI2R1tYjxvIC+NZiNdLd7vjsRL +Atz2R9B8hkvDEGB+aj4OqHuFCh8CgYEA0ox04N7yYkG8/i9Z+fQadgqSllgvb6w4 +hvKEhnwweu1q33n/YwZtQ89ElX0speK02ZH60AkNNXRRORVPCV60QhabXzax9Lba +J+m+NtAYPABwbXPRJq4S5z9toWoqxCxKc36sCJqjdDE637xtEe8ULh2WEGmCctjC +BpEk9xlMSp0CgYEArsLxu+RYUqCYiYZa5XnxC9OgUSaRpGdvwseAOEy0lI0AoxOm +tjO6JQnk0qbt26dO5a7JVPIklnmIskOMrBkcWJD2htuEwaixSDXHeQci2ROiqVSj +d9yHIWTWMjEOo+PpGnJcZkir3R5DJLRq0lnD42xN3KzPlOe8LcnTsPIlPPkCgYEA +qFZgREI8bM6+ekQFnlDKr0H4vXe4RYLelxZjWtsEL+SOpCp4RAYpaiPXY+X2wpKl +oaaTb60tAGYFYqxkyssLOCO3CcNDOLLRbUP3Lv/lwGNhgEEvIcvflUAjOQEXPE1l +IT5P8Xkh4o5R0fxnAAW0jsJc7rZM8+HWD0YQ1fdGBgkCgYEAvsEfq+E0t52Vvn+d +gxJE+N7Ny6Iu8cy47B0xKkyML//0vOquBun2cUYEqncloLI1a3wp1FykyJMJUX/d +ZTJl7u5hhLHkhxSDVmyccw4v3Zhsn5/qb18jseE42Nbhtf8VhkZLOSbiHmxjrNdH +V135E6sqWD6wkvGVbxn3haPe9+o= +-----END PRIVATE KEY----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 12:78:95:65:51:49:92:01:32:10 + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=Test Root CA + Validity + Not Before: Apr 6 16:18:41 2015 GMT + Not After : Apr 3 16:18:41 2025 GMT + Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:af:6a:a2:a5:e7:91:01:97:de:f8:53:18:af:0d: + f8:46:01:16:88:5f:93:94:20:ef:51:56:2f:7c:61: + 85:cc:12:82:06:0b:d2:1c:52:d7:c5:c8:c3:73:ab: + 26:91:df:41:f3:b2:58:6c:42:bb:a7:97:72:7d:be: + 87:99:01:4f:73:87:f8:eb:e6:45:bf:3c:a1:4b:d0: + 33:1e:a0:a5:04:4e:80:c5:0a:f6:5a:2d:9a:09:96: + 34:59:f2:06:71:3d:9e:fe:a8:19:bf:45:a9:dc:20: + c8:e6:9b:07:1e:fe:ff:ab:c2:1e:e4:fe:0b:75:49: + bc:a1:1b:bc:03:fb:c4:b3:c4:2f:40:05:84:70:8b: + d4:5b:b8:a7:5f:67:e2:9f:a6:8b:d4:da:e4:4f:8b: + c2:58:c5:29:b6:76:b8:19:0a:ce:00:11:51:62:22: + 3b:e0:90:db:f6:ae:7f:77:c3:1f:db:95:3d:1f:e2: + 7b:1e:ee:81:5b:a1:e7:12:15:3d:d4:d4:7b:b5:3f: + c3:19:3f:fb:4b:11:f8:63:3d:67:3f:7a:2b:44:88: + 82:9d:05:55:4c:31:07:0e:d6:14:17:a5:b2:c2:4e: + 77:55:86:66:0e:39:dd:7c:f8:6f:e1:92:4b:b0:ca: + 78:a0:b4:32:88:f2:44:10:1b:3e:b8:7a:6d:3d:b8: + 2b:03 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Subject Key Identifier: + 87:A2:09:4C:8C:84:57:D1:4A:30:35:53:8C:1D:04:01:18:21:15:CA + X509v3 Authority Key Identifier: + keyid:BC:F7:30:D1:3C:C0:F2:79:FA:EF:9F:C9:6C:5C:93:F3:8A:68:AB:83 + + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Subject Alternative Name: + DNS:localhost + Signature Algorithm: sha256WithRSAEncryption + 9f:37:2e:c1:f9:7d:09:d6:94:52:09:bd:f1:b2:f7:3e:67:6e: + 10:0b:65:cb:0e:c4:e7:cc:f7:25:9f:01:c0:e1:41:65:eb:bd: + 61:f8:89:be:73:29:ad:07:15:98:89:ea:f0:77:d6:8e:20:35: + 2b:0e:f3:64:05:f2:f0:20:73:56:23:0d:51:d9:19:b5:a8:cc: + a4:87:bb:63:2f:d1:e0:52:d0:5e:ae:93:c7:90:81:78:36:d4: + e6:a5:cc:db:c6:be:af:17:5b:80:83:34:2b:2d:dc:1e:f3:4c: + a0:04:70:f4:aa:90:1d:08:65:20:54:e1:32:5f:80:12:3e:76: + aa:1b:b9:2f:a7:36:54:99:a3:45:e4:43:1b:08:17:11:81:d0: + 32:1d:68:c2:d1:b1:33:04:92:95:63:b8:26:18:79:12:ab:77: + 14:80:58:4a:8a:a4:4e:ec:2e:07:02:22:de:67:92:03:54:0f: + 31:6e:15:aa:53:6a:40:5b:d0:04:4e:c9:dc:a3:2a:0b:52:c9: + 8b:92:9b:f4:4a:11:1b:e8:c1:da:54:9b:5c:ac:62:85:ce:ac: + 9a:3d:0e:f5:4c:be:9d:53:5b:3e:bb:c0:a2:fe:a7:b2:10:eb: + 02:d5:ce:ea:86:05:6e:77:c3:23:2d:45:c1:37:98:7b:6c:89: + 13:92:95:8b +-----BEGIN CERTIFICATE----- +MIIDgjCCAmqgAwIBAgIKEniVZVFJkgEyEDANBgkqhkiG9w0BAQsFADAXMRUwEwYD +VQQDDAxUZXN0IFJvb3QgQ0EwHhcNMTUwNDA2MTYxODQxWhcNMjUwNDAzMTYxODQx +WjBgMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +TW91bnRhaW4gVmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJbG9jYWxo +b3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr2qipeeRAZfe+FMY +rw34RgEWiF+TlCDvUVYvfGGFzBKCBgvSHFLXxcjDc6smkd9B87JYbEK7p5dyfb6H +mQFPc4f46+ZFvzyhS9AzHqClBE6AxQr2Wi2aCZY0WfIGcT2e/qgZv0Wp3CDI5psH +Hv7/q8Ie5P4LdUm8oRu8A/vEs8QvQAWEcIvUW7inX2fin6aL1NrkT4vCWMUptna4 +GQrOABFRYiI74JDb9q5/d8Mf25U9H+J7Hu6BW6HnEhU91NR7tT/DGT/7SxH4Yz1n +P3orRIiCnQVVTDEHDtYUF6Wywk53VYZmDjndfPhv4ZJLsMp4oLQyiPJEEBs+uHpt +PbgrAwIDAQABo4GGMIGDMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFIeiCUyMhFfR +SjA1U4wdBAEYIRXKMB8GA1UdIwQYMBaAFLz3MNE8wPJ5+u+fyWxck/OKaKuDMB0G +A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAUBgNVHREEDTALgglsb2NhbGhv +c3QwDQYJKoZIhvcNAQELBQADggEBAJ83LsH5fQnWlFIJvfGy9z5nbhALZcsOxOfM +9yWfAcDhQWXrvWH4ib5zKa0HFZiJ6vB31o4gNSsO82QF8vAgc1YjDVHZGbWozKSH +u2Mv0eBS0F6uk8eQgXg21OalzNvGvq8XW4CDNCst3B7zTKAEcPSqkB0IZSBU4TJf +gBI+dqobuS+nNlSZo0XkQxsIFxGB0DIdaMLRsTMEkpVjuCYYeRKrdxSAWEqKpE7s +LgcCIt5nkgNUDzFuFapTakBb0AROydyjKgtSyYuSm/RKERvowdpUm1ysYoXOrJo9 +DvVMvp1TWz67wKL+p7IQ6wLVzuqGBW53wyMtRcE3mHtsiROSlYs= +-----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/ee.cnf b/net/data/ssl/scripts/ee.cnf index fa2a89b6..0151613 100644 --- a/net/data/ssl/scripts/ee.cnf +++ b/net/data/ssl/scripts/ee.cnf
@@ -25,12 +25,22 @@ O = Bar CN = Duplicate +[req_localhost_cn] +C = US +ST = California +L = Mountain View +O = Test CA +CN = localhost + [req_punycode_dn] CN = xn--wgv71a119e.com [req_extensions] subjectAltName = IP:127.0.0.1 +[req_localhost_san] +subjectAltName = DNS:localhost + [req_punycode] basicConstraints = critical, CA:true subjectAltName = @punycode_san
diff --git a/net/data/ssl/scripts/generate-aia-certs.sh b/net/data/ssl/scripts/generate-aia-certs.sh index 76b86cf..706d386ee 100755 --- a/net/data/ssl/scripts/generate-aia-certs.sh +++ b/net/data/ssl/scripts/generate-aia-certs.sh
@@ -8,8 +8,7 @@ # certificates that can be used to test fetching of an intermediate via AIA. try() { - echo "$@" - "$@" || exit 1 + "$@" || (e=$?; echo "$@" > /dev/stderr; exit $e) } try rm -rf out
diff --git a/net/data/ssl/scripts/generate-cross-signed-certs.sh b/net/data/ssl/scripts/generate-cross-signed-certs.sh index f5a7024..23d20e29 100755 --- a/net/data/ssl/scripts/generate-cross-signed-certs.sh +++ b/net/data/ssl/scripts/generate-cross-signed-certs.sh
@@ -19,12 +19,7 @@ # MD5root, or leaf -> MD5root -> SHA256root try() { - echo "$@" - "$@" || exit 1 -} - -quiet_try() { - "$@" || exit 1 + "$@" || (e=$?; echo "$@" > /dev/stderr; exit $e) } try rm -rf out @@ -85,9 +80,9 @@ -out out/ok_cert.pem \ -config ca.cnf -quiet_try openssl x509 -text \ +try openssl x509 -text \ -in out/2048-md5-root.pem > ../certificates/cross-signed-root-md5.pem -quiet_try openssl x509 -text \ +try openssl x509 -text \ -in out/2048-sha256-root.pem > ../certificates/cross-signed-root-sha256.pem -quiet_try openssl x509 -text \ +try openssl x509 -text \ -in out/ok_cert.pem > ../certificates/cross-signed-leaf.pem
diff --git a/net/data/ssl/scripts/generate-policy-certs.sh b/net/data/ssl/scripts/generate-policy-certs.sh index 5507d5b..bef21f4 100755 --- a/net/data/ssl/scripts/generate-policy-certs.sh +++ b/net/data/ssl/scripts/generate-policy-certs.sh
@@ -11,8 +11,7 @@ # When validating, supplying no policy OID should not result in an error. try() { - echo "$@" - "$@" || exit 1 + "$@" || (e=$?; echo "$@" > /dev/stderr; exit $e) } try rm -rf out
diff --git a/net/data/ssl/scripts/generate-test-certs.sh b/net/data/ssl/scripts/generate-test-certs.sh index 24eadf1..b0fd908 100755 --- a/net/data/ssl/scripts/generate-test-certs.sh +++ b/net/data/ssl/scripts/generate-test-certs.sh
@@ -8,8 +8,7 @@ # certificates that can be used to test fetching of an intermediate via AIA. try() { - echo "$@" - "$@" || exit 1 + "$@" || (e=$?; echo "$@" > /dev/stderr; exit $e) } try rm -rf out @@ -33,11 +32,10 @@ try openssl x509 \ -req -days 3650 \ -in out/2048-sha256-root.req \ - -out out/2048-sha256-root.pem \ -signkey out/2048-sha256-root.key \ -extfile ca.cnf \ -extensions ca_cert \ - -text + -text > out/2048-sha256-root.pem # Generate the leaf certificate requests try openssl req \ @@ -52,6 +50,14 @@ -out out/ok_cert.req \ -config ee.cnf +SUBJECT_NAME=req_localhost_cn \ +try openssl req \ + -new \ + -keyout out/localhost_cert.key \ + -out out/localhost_cert.req \ + -reqexts req_localhost_san \ + -config ee.cnf + # Generate the leaf certificates CA_COMMON_NAME="Test Root CA" \ try openssl ca \ @@ -92,8 +98,19 @@ -out out/name_constraint_good.pem \ -config ca.cnf +CA_COMMON_NAME="Test Root CA" \ + try openssl ca \ + -batch \ + -extensions user_cert \ + -days 3650 \ + -in out/localhost_cert.req \ + -out out/localhost_cert.pem \ + -config ca.cnf + try /bin/sh -c "cat out/ok_cert.key out/ok_cert.pem \ > ../certificates/ok_cert.pem" +try /bin/sh -c "cat out/localhost_cert.key out/localhost_cert.pem \ + > ../certificates/localhost_cert.pem" try /bin/sh -c "cat out/expired_cert.key out/expired_cert.pem \ > ../certificates/expired_cert.pem" try /bin/sh -c "cat out/2048-sha256-root.key out/2048-sha256-root.pem \ @@ -108,7 +125,7 @@ try openssl req -x509 -days 3650 \ -config ../scripts/ee.cnf -newkey rsa:2048 -text \ -sha256 \ - -out sha256.pem + -out ../certificates/sha256.pem ## Self-signed cert for SPDY/QUIC/HTTP2 pooling testing try openssl req -x509 -days 3650 -extensions req_spdy_pooling \
diff --git a/net/data/url_request_unittest/hpkp-headers.html.mock-http-headers b/net/data/url_request_unittest/hpkp-headers.html.mock-http-headers index db38dc1..1ee3470 100644 --- a/net/data/url_request_unittest/hpkp-headers.html.mock-http-headers +++ b/net/data/url_request_unittest/hpkp-headers.html.mock-http-headers
@@ -3,4 +3,4 @@ Content-Type: text/html; charset=ISO-8859-1 X-Multiple-Entries: a X-Multiple-Entries: b -Public-Key-Pins: max-age=50000; pin-sha1="K9e3/nFL5j90GuVJOJBv6WXpvcs="; pin-sha256="2zCMVDKgnKec0721Sp1zVh2yiHeW/LJK4STkNnEa1og="; pin-sha1="YeyCi9tceCqPzE8PFLuFMZOf9z0=" +Public-Key-Pins: max-age=50000; pin-sha1="K9e3/nFL5j90GuVJOJBv6WXpvcs="; pin-sha256="+TTrWvvJdM9gwuHiLTApo/2DBT2xb4hBPRJDI9pebXY="; pin-sha1="PshSs8WOjC7qwaYMv0T3rJDwKS4="
diff --git a/net/data/url_request_unittest/hsts-and-hpkp-headers.html.mock-http-headers b/net/data/url_request_unittest/hsts-and-hpkp-headers.html.mock-http-headers index 95f923a..2bcfd2a 100644 --- a/net/data/url_request_unittest/hsts-and-hpkp-headers.html.mock-http-headers +++ b/net/data/url_request_unittest/hsts-and-hpkp-headers.html.mock-http-headers
@@ -5,4 +5,4 @@ X-Multiple-Entries: b Strict-Transport-Security: max-age=12300 Strict-Transport-Security: max-age=12300; includeSubdomains -Public-Key-Pins: max-age=50000; pin-sha1="Wws2/Z7YhKlX73v3rYHBBxO4OLE="; pin-sha256="2zCMVDKgnKec0721Sp1zVh2yiHeW/LJK4STkNnEa1og=" +Public-Key-Pins: max-age=50000; pin-sha1="Wws2/Z7YhKlX73v3rYHBBxO4OLE="; pin-sha256="+TTrWvvJdM9gwuHiLTApo/2DBT2xb4hBPRJDI9pebXY="
diff --git a/net/data/url_request_unittest/hsts-and-hpkp-headers2.html.mock-http-headers b/net/data/url_request_unittest/hsts-and-hpkp-headers2.html.mock-http-headers index e6090ee..f4b9aed 100644 --- a/net/data/url_request_unittest/hsts-and-hpkp-headers2.html.mock-http-headers +++ b/net/data/url_request_unittest/hsts-and-hpkp-headers2.html.mock-http-headers
@@ -4,5 +4,5 @@ X-Multiple-Entries: a X-Multiple-Entries: b Strict-Transport-Security: max-age=12300; includeSubdomains -Public-Key-Pins: max-age=50000; pin-sha1="K9e3/nFL5j90GuVJOJBv6WXpvcs="; pin-sha256="2zCMVDKgnKec0721Sp1zVh2yiHeW/LJK4STkNnEa1og="; pin-sha1="YeyCi9tceCqPzE8PFLuFMZOf9z0=" -Public-Key-Pins: max-age=50000; pin-sha1="K9e3/nFL5j90GuVJOJBv6WXpvcs="; pin-sha256="2zCMVDKgnKec0721Sp1zVh2yiHeW/LJK4STkNnEa1og="; pin-sha1="YeyCi9tceCqPzE8PFLuFMZOf9z0="; includeSubdomains +Public-Key-Pins: max-age=50000; pin-sha1="K9e3/nFL5j90GuVJOJBv6WXpvcs="; pin-sha256="+TTrWvvJdM9gwuHiLTApo/2DBT2xb4hBPRJDI9pebXY="; pin-sha1="PshSs8WOjC7qwaYMv0T3rJDwKS4=" +Public-Key-Pins: max-age=50000; pin-sha1="K9e3/nFL5j90GuVJOJBv6WXpvcs="; pin-sha256="+TTrWvvJdM9gwuHiLTApo/2DBT2xb4hBPRJDI9pebXY="; pin-sha1="PshSs8WOjC7qwaYMv0T3rJDwKS4="
diff --git a/net/filter/sdch_filter.h b/net/filter/sdch_filter.h index 9541742..68febc6 100644 --- a/net/filter/sdch_filter.h +++ b/net/filter/sdch_filter.h
@@ -18,6 +18,7 @@ #include "base/memory/scoped_ptr.h" #include "net/base/net_export.h" +#include "net/base/sdch_dictionary.h" #include "net/base/sdch_manager.h" #include "net/filter/filter.h" @@ -95,7 +96,7 @@ // Validity of this pointer is guaranteed by either the FilterContext holding // a containing SdchManager::DictionarySet, or this object holding a // container in |unexpected_dictionary_handle_| below. - const SdchManager::Dictionary *dictionary_; + const SdchDictionary* dictionary_; // We keep a copy of the URLRequestContext for use in the destructor, (at // which point GetURLRequestContext() will likely return null because of
diff --git a/net/filter/sdch_filter_unittest.cc b/net/filter/sdch_filter_unittest.cc index 59ad2c3..1fecd086 100644 --- a/net/filter/sdch_filter_unittest.cc +++ b/net/filter/sdch_filter_unittest.cc
@@ -13,6 +13,8 @@ #include "base/test/histogram_tester.h" #include "base/test/simple_test_clock.h" #include "net/base/io_buffer.h" +#include "net/base/sdch_dictionary.h" +#include "net/base/sdch_manager.h" #include "net/base/sdch_observer.h" #include "net/filter/mock_filter_context.h" #include "net/filter/sdch_filter.h" @@ -1220,9 +1222,8 @@ ASSERT_TRUE(hash_set); ASSERT_EQ(SDCH_OK, problem_code); - const_cast<SdchManager::Dictionary*>( - hash_set->GetDictionary(server_hash))->SetClockForTesting( - clock.Pass()); + const_cast<SdchDictionary*>(hash_set->GetDictionary(server_hash)) + ->SetClockForTesting(clock.Pass()); // Encode output with the second dictionary. std::string sdch_compressed(NewSdchCompressedData(expired_dictionary));
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index d4a1727a..bea5447 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -1494,8 +1494,14 @@ if (ShouldForceSpdySSL()) return ClientSocketPoolManager::SSL_GROUP; - return ClientSocketPoolManager::GroupTypeFromScheme( - alternative_service_url_.scheme()); + std::string scheme = alternative_service_url_.scheme(); + if (scheme == "ftp") + return ClientSocketPoolManager::FTP_GROUP; + + if (scheme == "https" || scheme == "wss") + return ClientSocketPoolManager::SSL_GROUP; + + return ClientSocketPoolManager::NORMAL_GROUP; } } // namespace net
diff --git a/net/net.gyp b/net/net.gyp index a58aaad..5f57bca 100644 --- a/net/net.gyp +++ b/net/net.gyp
@@ -233,7 +233,7 @@ # Only include this test when on Posix and using NSS for # cert verification or on iOS (which also uses NSS for certs). 'sources!': [ - 'ocsp/nss_ocsp_unittest.cc', + 'cert_net/nss_ocsp_unittest.cc', ], }], [ 'use_openssl==1', { @@ -253,7 +253,7 @@ 'cert/x509_util_openssl_unittest.cc', 'quic/test_tools/crypto_test_utils_openssl.cc', 'socket/ssl_client_socket_openssl_unittest.cc', - 'socket/ssl_session_cache_openssl_unittest.cc', + 'ssl/ssl_client_session_cache_openssl_unittest.cc', ], }, ], @@ -380,6 +380,7 @@ # Need to read input data files. 'filter/gzip_filter_unittest.cc', # Need TestServer. + "cert_net/cert_net_fetcher_impl_unittest.cc", 'proxy/proxy_script_fetcher_impl_unittest.cc', 'socket/ssl_client_socket_unittest.cc', 'socket/ssl_server_socket_unittest.cc',
diff --git a/net/net.gypi b/net/net.gypi index 5449bac..cbdc7e4 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -129,8 +129,6 @@ 'socket/ssl_client_socket_openssl.h', 'socket/ssl_client_socket_pool.cc', 'socket/ssl_client_socket_pool.h', - 'socket/ssl_session_cache_openssl.cc', - 'socket/ssl_session_cache_openssl.h', 'socket/ssl_socket.h', 'ssl/channel_id_service.cc', 'ssl/channel_id_service.h', @@ -154,6 +152,8 @@ 'ssl/ssl_client_auth_cache.cc', 'ssl/ssl_client_auth_cache.h', 'ssl/ssl_client_cert_type.h', + 'ssl/ssl_client_session_cache_openssl.cc', + 'ssl/ssl_client_session_cache_openssl.h', 'ssl/ssl_config.cc', 'ssl/ssl_config.h', 'ssl/ssl_config_service.cc', @@ -271,6 +271,8 @@ 'base/proxy_delegate.h', 'base/request_priority.cc', 'base/request_priority.h', + 'base/sdch_dictionary.cc', + 'base/sdch_dictionary.h', 'base/sdch_manager.cc', 'base/sdch_manager.h', 'base/sdch_net_log_params.cc', @@ -303,6 +305,7 @@ 'cert/cert_database_mac.cc', 'cert/cert_database_nss.cc', 'cert/cert_database_win.cc', + 'cert/cert_net_fetcher.h', 'cert/cert_trust_anchor_provider.h', 'cert/cert_verify_proc.cc', 'cert/cert_verify_proc.h', @@ -375,6 +378,8 @@ 'cert/x509_util_mac.h', 'cert/x509_util_nss.cc', 'cert/x509_util_nss.h', + 'cert_net/cert_net_fetcher_impl.cc', + 'cert_net/cert_net_fetcher_impl.h', 'cookies/canonical_cookie.cc', 'cookies/canonical_cookie.h', 'cookies/cookie_constants.cc', @@ -481,6 +486,8 @@ 'log/trace_net_log_observer.cc', 'log/trace_net_log_observer.h', 'disk_cache/simple/simple_histogram_macros.h' , + 'cert_net/nss_ocsp.cc', + 'cert_net/nss_ocsp.h', 'disk_cache/simple/simple_index.cc', 'disk_cache/simple/simple_index.h', 'disk_cache/simple/simple_index_delegate.h', @@ -690,8 +697,6 @@ 'http/url_security_manager.h', 'http/url_security_manager_posix.cc', 'http/url_security_manager_win.cc', - 'ocsp/nss_ocsp.cc', - 'ocsp/nss_ocsp.h', 'proxy/dhcp_proxy_script_adapter_fetcher_win.cc', 'proxy/dhcp_proxy_script_adapter_fetcher_win.h', 'proxy/dhcp_proxy_script_fetcher.cc', @@ -1284,6 +1289,7 @@ 'base/prioritized_dispatcher_unittest.cc', 'base/priority_queue_unittest.cc', 'base/registry_controlled_domains/registry_controlled_domain_unittest.cc', + 'base/sdch_dictionary_unittest.cc', 'base/sdch_manager_unittest.cc', 'base/static_cookie_policy_unittest.cc', 'base/test_completion_callback_unittest.cc', @@ -1314,6 +1320,8 @@ 'cert/x509_util_nss_unittest.cc', 'cert/x509_util_openssl_unittest.cc', 'cert/x509_util_unittest.cc', + 'cert_net/cert_net_fetcher_impl_unittest.cc', + 'cert_net/nss_ocsp_unittest.cc', 'cookies/canonical_cookie_unittest.cc', 'cookies/cookie_constants_unittest.cc', 'cookies/cookie_monster_unittest.cc', @@ -1431,7 +1439,6 @@ 'log/net_log_unittest.h', 'log/net_log_util_unittest.cc', 'log/trace_net_log_observer_unittest.cc', - 'ocsp/nss_ocsp_unittest.cc', 'proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc', 'proxy/dhcp_proxy_script_fetcher_factory_unittest.cc', 'proxy/dhcp_proxy_script_fetcher_win_unittest.cc', @@ -1603,7 +1610,6 @@ 'socket/ssl_client_socket_pool_unittest.cc', 'socket/ssl_client_socket_unittest.cc', 'socket/ssl_server_socket_unittest.cc', - 'socket/ssl_session_cache_openssl_unittest.cc', 'socket/tcp_client_socket_unittest.cc', 'socket/tcp_listen_socket_unittest.cc', 'socket/tcp_listen_socket_unittest.h', @@ -1671,6 +1677,7 @@ 'ssl/openssl_client_key_store_unittest.cc', 'ssl/ssl_cipher_suite_names_unittest.cc', 'ssl/ssl_client_auth_cache_unittest.cc', + 'ssl/ssl_client_session_cache_openssl_unittest.cc', 'ssl/ssl_config_service_unittest.cc', 'ssl/ssl_connection_status_flags_unittest.cc', 'test/embedded_test_server/embedded_test_server_unittest.cc',
diff --git a/net/net_common.gypi b/net/net_common.gypi index 4f97ff2..7411efa4 100644 --- a/net/net_common.gypi +++ b/net/net_common.gypi
@@ -147,8 +147,8 @@ 'cert/x509_certificate_nss.cc', 'cert/x509_util_nss.cc', 'cert/x509_util_nss.h', - 'ocsp/nss_ocsp.cc', - 'ocsp/nss_ocsp.h', + 'cert_net/nss_ocsp.cc', + 'cert_net/nss_ocsp.h', 'quic/crypto/aead_base_decrypter_nss.cc', 'quic/crypto/aead_base_encrypter_nss.cc', 'quic/crypto/aes_128_gcm_12_decrypter_nss.cc', @@ -197,13 +197,13 @@ 'socket/ssl_client_socket_openssl.h', 'socket/ssl_server_socket_openssl.cc', 'socket/ssl_server_socket_openssl.h', - 'socket/ssl_session_cache_openssl.cc', - 'socket/ssl_session_cache_openssl.h', 'ssl/openssl_platform_key.h', 'ssl/openssl_platform_key_mac.cc', 'ssl/openssl_platform_key_win.cc', 'ssl/openssl_ssl_util.cc', 'ssl/openssl_ssl_util.h', + 'ssl/ssl_client_session_cache_openssl.cc', + 'ssl/ssl_client_session_cache_openssl.h', ], 'conditions': [ # Pull in the bundled or system NSS as appropriate. @@ -273,8 +273,8 @@ 'cert/nss_cert_database.h', 'cert/test_root_certs_nss.cc', 'cert/x509_certificate_nss.cc', - 'ocsp/nss_ocsp.cc', - 'ocsp/nss_ocsp.h', + 'cert_net/nss_ocsp.cc', + 'cert_net/nss_ocsp.h', 'third_party/mozilla_security_manager/nsKeygenHandler.cpp', 'third_party/mozilla_security_manager/nsKeygenHandler.h', 'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp', @@ -417,10 +417,10 @@ ['include', '^cert/test_root_certs_nss\\.cc$'], ['include', '^cert/x509_util_nss\\.cc$'], ['include', '^cert/x509_util_nss\\.h$'], + ['include', '^cert_net/nss_ocsp\\.cc$'], + ['include', '^cert_net/nss_ocsp\\.h$'], ['include', '^proxy/proxy_resolver_mac\\.cc$'], ['include', '^proxy/proxy_server_mac\\.cc$'], - ['include', '^ocsp/nss_ocsp\\.cc$'], - ['include', '^ocsp/nss_ocsp\\.h$'], ], }], ],
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index 8dab0bf4..421dc93 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc
@@ -327,18 +327,6 @@ } // namespace -// static -ClientSocketPoolManager::SocketGroupType -ClientSocketPoolManager::GroupTypeFromScheme(const std::string& scheme) { - if (scheme == "ftp") - return FTP_GROUP; - - if (scheme == "https" || scheme == "wss") - return SSL_GROUP; - - return NORMAL_GROUP; -} - ClientSocketPoolManager::ClientSocketPoolManager() {} ClientSocketPoolManager::~ClientSocketPoolManager() {}
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h index 45ed401a..9b4a065 100644 --- a/net/socket/client_socket_pool_manager.h +++ b/net/socket/client_socket_pool_manager.h
@@ -50,9 +50,6 @@ FTP_GROUP // For FTP sockets (over an HTTP proxy). }; - // Returns the correct socket group type for |scheme|. - static SocketGroupType GroupTypeFromScheme(const std::string& scheme); - ClientSocketPoolManager(); virtual ~ClientSocketPoolManager();
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index b7beae1..99320ef 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc
@@ -100,9 +100,9 @@ #include "net/cert/single_request_cert_verifier.h" #include "net/cert/x509_certificate_net_log_param.h" #include "net/cert/x509_util.h" +#include "net/cert_net/nss_ocsp.h" #include "net/http/transport_security_state.h" #include "net/log/net_log.h" -#include "net/ocsp/nss_ocsp.h" #include "net/socket/client_socket_handle.h" #include "net/socket/nss_ssl_util.h" #include "net/ssl/ssl_cert_request_info.h"
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index a3263f8..c9c23f41 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc
@@ -34,9 +34,9 @@ #include "net/cert/x509_certificate_net_log_param.h" #include "net/cert/x509_util_openssl.h" #include "net/http/transport_security_state.h" -#include "net/socket/ssl_session_cache_openssl.h" #include "net/ssl/scoped_openssl_types.h" #include "net/ssl/ssl_cert_request_info.h" +#include "net/ssl/ssl_client_session_cache_openssl.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" @@ -164,7 +164,7 @@ public: static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } - SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; } + SSLClientSessionCacheOpenSSL* session_cache() { return &session_cache_; } SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) { DCHECK(ssl); @@ -181,12 +181,11 @@ private: friend struct DefaultSingletonTraits<SSLContext>; - SSLContext() { + SSLContext() : session_cache_(SSLClientSessionCacheOpenSSL::Config()) { crypto::EnsureOpenSSLInit(); ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); DCHECK_NE(ssl_socket_data_index_, -1); ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); - session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL); SSL_CTX_set_cert_cb(ssl_ctx_.get(), ClientCertRequestCallback, NULL); SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL); @@ -200,6 +199,12 @@ SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, NULL); ssl_ctx_->tlsext_channel_id_enabled_new = 1; + SSL_CTX_set_info_callback(ssl_ctx_.get(), InfoCallback); + + // Disable the internal session cache. Session caching is handled + // externally (i.e. by SSLClientSessionCacheOpenSSL). + SSL_CTX_set_session_cache_mode( + ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL); scoped_ptr<base::Environment> env(base::Environment::Create()); std::string ssl_keylog_file; @@ -216,14 +221,6 @@ } } - static std::string GetSessionCacheKey(const SSL* ssl) { - SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); - CHECK(socket); - return socket->GetSessionCacheKey(); - } - - static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; - static int ClientCertRequestCallback(SSL* ssl, void* arg) { SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); DCHECK(socket); @@ -247,13 +244,23 @@ return socket->SelectNextProtoCallback(out, outlen, in, inlen); } + static void InfoCallback(const SSL* ssl, int type, int val) { + SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); + socket->InfoCallback(type, val); + } + // This is the index used with SSL_get_ex_data to retrieve the owner // SSLClientSocketOpenSSL object from an SSL instance. int ssl_socket_data_index_; ScopedSSL_CTX ssl_ctx_; - // |session_cache_| must be destroyed before |ssl_ctx_|. - SSLSessionCacheOpenSSL session_cache_; + + // TODO(davidben): Use a separate cache per URLRequestContext. + // https://crbug.com/458365 + // + // TODO(davidben): Sessions should be invalidated on fatal + // alerts. https://crbug.com/466352 + SSLClientSessionCacheOpenSSL session_cache_; }; // PeerCertificateChain is a helper object which extracts the certificate @@ -338,15 +345,6 @@ } // static -SSLSessionCacheOpenSSL::Config - SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = { - &GetSessionCacheKey, // key_func - 1024, // max_entries - 256, // expiration_check_count - 60 * 60, // timeout_seconds -}; - -// static void SSLClientSocket::ClearSessionCache() { SSLClientSocketOpenSSL::SSLContext* context = SSLClientSocketOpenSSL::SSLContext::GetInstance(); @@ -382,10 +380,11 @@ host_and_port_(host_and_port), ssl_config_(ssl_config), ssl_session_cache_shard_(context.ssl_session_cache_shard), - trying_cached_session_(false), next_handshake_state_(STATE_NONE), npn_status_(kNextProtoUnsupported), channel_id_xtn_negotiated_(false), + handshake_completed_(false), + certificate_verified_(false), transport_security_state_(context.transport_security_state), policy_enforcer_(context.cert_policy_enforcer), net_log_(transport_->socket()->NetLog()), @@ -699,8 +698,9 @@ if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) return ERR_UNEXPECTED; - trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( - ssl_, GetSessionCacheKey()); + SSL_SESSION* session = context->session_cache()->Lookup(GetSessionCacheKey()); + if (session != nullptr) + SSL_set_session(ssl_, session); send_buffer_ = new GrowableIOBuffer(); send_buffer_->SetCapacity(KDefaultOpenSSLBufferSize); @@ -918,11 +918,6 @@ } if (rv == 1) { - if (trying_cached_session_ && logging::DEBUG_MODE) { - DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString() - << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail"); - } - if (ssl_config_.version_fallback && ssl_config_.version_max < ssl_config_.version_fallback_min) { return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION; @@ -1145,9 +1140,9 @@ // the connection. VerifyCT(); - // TODO(joth): Work out if we need to remember the intermediate CA certs - // when the server sends them to us, and do so here. - SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_); + DCHECK(!certificate_verified_); + certificate_verified_ = true; + MaybeCacheSession(); } else { DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) << " (" << result << ")"; @@ -1842,6 +1837,28 @@ bio, cmd, argp, argi, argl, retvalue); } +void SSLClientSocketOpenSSL::MaybeCacheSession() { + // Only cache the session once both the handshake has completed and the + // certificate has been verified. + if (!handshake_completed_ || !certificate_verified_ || + SSL_session_reused(ssl_)) { + return; + } + + SSLContext::GetInstance()->session_cache()->Insert(GetSessionCacheKey(), + SSL_get_session(ssl_)); +} + +void SSLClientSocketOpenSSL::InfoCallback(int type, int val) { + // Note that SSL_CB_HANDSHAKE_DONE may be signaled multiple times if the + // socket renegotiates. + if (type != SSL_CB_HANDSHAKE_DONE || handshake_completed_) + return; + + handshake_completed_ = true; + MaybeCacheSession(); +} + void SSLClientSocketOpenSSL::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const { for (ct::SCTList::const_iterator iter = ct_verify_result_.verified_scts.begin();
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h index f19813e..dc9c7e90 100644 --- a/net/socket/ssl_client_socket_openssl.h +++ b/net/socket/ssl_client_socket_openssl.h
@@ -166,6 +166,18 @@ const char *argp, int argi, long argl, long retvalue); + // Called after the initial handshake completes and after the server + // certificate has been verified. The order of handshake completion and + // certificate verification depends on whether the connection was false + // started. After both have happened (thus calling this twice), the session is + // safe to cache and will be cached. + void MaybeCacheSession(); + + // Callback from the SSL layer when the internal state machine progresses. It + // is used to listen for when the handshake completes entirely; |Connect| may + // return early if false starting. + void InfoCallback(int type, int val); + // Adds the SignedCertificateTimestamps from ct_verify_result_ to |ssl_info|. // SCTs are held in three separate vectors in ct_verify_result, each // vetor representing a particular verification state, this method associates @@ -264,9 +276,6 @@ // resume on the socket with a different value. const std::string ssl_session_cache_shard_; - // Used for session cache diagnostics. - bool trying_cached_session_; - enum State { STATE_NONE, STATE_HANDSHAKE, @@ -283,6 +292,10 @@ std::string channel_id_cert_; // True if channel ID extension was negotiated. bool channel_id_xtn_negotiated_; + // True if the initial handshake has completed. + bool handshake_completed_; + // True if the initial handshake's certificate has been verified. + bool certificate_verified_; // The request handle for |channel_id_service_|. ChannelIDService::RequestHandle channel_id_request_handle_;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 004810a..578456ad 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -348,6 +348,9 @@ int buf_len, const CompletionCallback& callback) override; + int pending_read_result() const { return pending_read_result_; } + IOBuffer* pending_read_buf() const { return pending_read_buf_.get(); } + // Blocks read results on the socket. Reads will not complete until // UnblockReadResult() has been called and a result is ready from the // underlying transport. Note: if BlockReadResult() is called while there is a @@ -377,6 +380,9 @@ // True if read callbacks are blocked. bool should_block_read_; + // The buffer for the pending read, or NULL if not consumed. + scoped_refptr<IOBuffer> pending_read_buf_; + // The user callback for the pending read call. CompletionCallback pending_read_callback_; @@ -414,6 +420,7 @@ int FakeBlockingStreamSocket::Read(IOBuffer* buf, int len, const CompletionCallback& callback) { + DCHECK(!pending_read_buf_); DCHECK(pending_read_callback_.is_null()); DCHECK_EQ(ERR_IO_PENDING, pending_read_result_); DCHECK(!callback.is_null()); @@ -422,9 +429,11 @@ &FakeBlockingStreamSocket::OnReadCompleted, base::Unretained(this))); if (rv == ERR_IO_PENDING) { // Save the callback to be called later. + pending_read_buf_ = buf; pending_read_callback_ = callback; } else if (should_block_read_) { // Save the callback and read result to be called later. + pending_read_buf_ = buf; pending_read_callback_ = callback; OnReadCompleted(rv); rv = ERR_IO_PENDING; @@ -471,6 +480,7 @@ if (pending_read_result_ == ERR_IO_PENDING) return; int result = pending_read_result_; + pending_read_buf_ = nullptr; pending_read_result_ = ERR_IO_PENDING; base::ResetAndReturn(&pending_read_callback_).Run(result); } @@ -538,7 +548,8 @@ read_loop_->Quit(); } else { // Either the Read() was never blocked or UnblockReadResult() was called - // before the Read() completed. Either way, run the callback. + // before the Read() completed. Either way, return the result to the caller. + pending_read_buf_ = nullptr; base::ResetAndReturn(&pending_read_callback_).Run(result); } } @@ -2812,6 +2823,85 @@ // attempt to read one byte extra. } +// Tests that basic session resumption works. +TEST_F(SSLClientSocketTest, SessionResumption) { + SpawnedTestServer::SSLOptions ssl_options; + ASSERT_TRUE(StartTestServer(ssl_options)); + + // First, perform a full handshake. + SSLConfig ssl_config; + TestCompletionCallback callback; + scoped_ptr<StreamSocket> transport( + new TCPClientSocket(addr(), &log_, NetLog::Source())); + ASSERT_EQ(OK, callback.GetResult(transport->Connect(callback.callback()))); + scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( + transport.Pass(), test_server()->host_port_pair(), ssl_config)); + ASSERT_EQ(OK, callback.GetResult(sock->Connect(callback.callback()))); + SSLInfo ssl_info; + ASSERT_TRUE(sock->GetSSLInfo(&ssl_info)); + EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); + + // The next connection should resume. + transport.reset(new TCPClientSocket(addr(), &log_, NetLog::Source())); + ASSERT_EQ(OK, callback.GetResult(transport->Connect(callback.callback()))); + sock = CreateSSLClientSocket(transport.Pass(), + test_server()->host_port_pair(), ssl_config); + ASSERT_EQ(OK, callback.GetResult(sock->Connect(callback.callback()))); + ASSERT_TRUE(sock->GetSSLInfo(&ssl_info)); + EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, ssl_info.handshake_type); + + // Using a different HostPortPair uses a different session cache key. + transport.reset(new TCPClientSocket(addr(), &log_, NetLog::Source())); + ASSERT_EQ(OK, callback.GetResult(transport->Connect(callback.callback()))); + sock = CreateSSLClientSocket(transport.Pass(), + HostPortPair("example.com", 443), ssl_config); + ASSERT_EQ(OK, callback.GetResult(sock->Connect(callback.callback()))); + ASSERT_TRUE(sock->GetSSLInfo(&ssl_info)); + EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); + + SSLClientSocket::ClearSessionCache(); + + // After clearing the session cache, the next handshake doesn't resume. + transport.reset(new TCPClientSocket(addr(), &log_, NetLog::Source())); + ASSERT_EQ(OK, callback.GetResult(transport->Connect(callback.callback()))); + sock = CreateSSLClientSocket(transport.Pass(), + test_server()->host_port_pair(), ssl_config); + ASSERT_EQ(OK, callback.GetResult(sock->Connect(callback.callback()))); + ASSERT_TRUE(sock->GetSSLInfo(&ssl_info)); + EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); +} + +// Tests that connections with certificate errors do not add entries to the +// session cache. +TEST_F(SSLClientSocketTest, CertificateErrorNoResume) { + SpawnedTestServer::SSLOptions ssl_options; + ASSERT_TRUE(StartTestServer(ssl_options)); + + cert_verifier_->set_default_result(ERR_CERT_COMMON_NAME_INVALID); + + SSLConfig ssl_config; + TestCompletionCallback callback; + scoped_ptr<StreamSocket> transport( + new TCPClientSocket(addr(), &log_, NetLog::Source())); + ASSERT_EQ(OK, callback.GetResult(transport->Connect(callback.callback()))); + scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket( + transport.Pass(), test_server()->host_port_pair(), ssl_config)); + EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, + callback.GetResult(sock->Connect(callback.callback()))); + + cert_verifier_->set_default_result(OK); + + // The next connection should perform a full handshake. + transport.reset(new TCPClientSocket(addr(), &log_, NetLog::Source())); + ASSERT_EQ(OK, callback.GetResult(transport->Connect(callback.callback()))); + sock = CreateSSLClientSocket(transport.Pass(), + test_server()->host_port_pair(), ssl_config); + ASSERT_EQ(OK, callback.GetResult(sock->Connect(callback.callback()))); + SSLInfo ssl_info; + ASSERT_TRUE(sock->GetSSLInfo(&ssl_info)); + EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); +} + // Tests that session caches are sharded by max_version. TEST_F(SSLClientSocketTest, FallbackShardSessionCache) { SpawnedTestServer::SSLOptions ssl_options; @@ -3105,9 +3195,9 @@ EXPECT_EQ(SSLInfo::HANDSHAKE_RESUME, ssl_info.handshake_type); } -// Test that sessions are not resumable before receiving the server Finished -// message. -TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBeforeFinish) { +// Test that False Started sessions are not resumable before receiving the +// server Finished message. +TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBeforeFinished) { if (!SupportsAESGCM()) { LOG(WARNING) << "Skipping test because AES-GCM is not supported."; return; @@ -3142,8 +3232,8 @@ // // The actual read on |sock1| will not complete until the Finished message is // processed; however, pump the underlying transport so that it is read from - // the socket. This still has the potential to race, but is generally unlikely - // due to socket buffer sizes. + // the socket. NOTE: This may flakily pass if the server's final flight + // doesn't come in one Read. scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); int rv = sock1->Read(buf.get(), 4096, callback.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -3168,6 +3258,78 @@ EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); } +// Test that False Started sessions are not resumable if the server Finished +// message was bad. +TEST_F(SSLClientSocketFalseStartTest, NoSessionResumptionBadFinished) { + if (!SupportsAESGCM()) { + LOG(WARNING) << "Skipping test because AES-GCM is not supported."; + return; + } + + // Start a server. + SpawnedTestServer::SSLOptions server_options; + server_options.key_exchanges = + SpawnedTestServer::SSLOptions::KEY_EXCHANGE_ECDHE_RSA; + server_options.bulk_ciphers = + SpawnedTestServer::SSLOptions::BULK_CIPHER_AES128GCM; + server_options.enable_npn = true; + ASSERT_TRUE(StartTestServer(server_options)); + + SSLConfig client_config; + client_config.next_protos.push_back(kProtoHTTP11); + + // Start a handshake up to the server Finished message. + TestCompletionCallback callback; + FakeBlockingStreamSocket* raw_transport1 = NULL; + scoped_ptr<SSLClientSocket> sock1; + ASSERT_NO_FATAL_FAILURE(CreateAndConnectUntilServerFinishedReceived( + client_config, &callback, &raw_transport1, &sock1)); + // Although raw_transport1 has the server Finished blocked, the handshake + // still completes. + EXPECT_EQ(OK, callback.WaitForResult()); + + // Continue to block the client (|sock1|) from processing the Finished + // message, but allow it to arrive on the socket. This ensures that, from the + // server's point of view, it has completed the handshake and added the + // session to its session cache. + // + // The actual read on |sock1| will not complete until the Finished message is + // processed; however, pump the underlying transport so that it is read from + // the socket. + scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); + int rv = sock1->Read(buf.get(), 4096, callback.callback()); + EXPECT_EQ(ERR_IO_PENDING, rv); + raw_transport1->WaitForReadResult(); + + // The server's second leg, or part of it, is now received but not yet sent to + // |sock1|. Before doing so, break the server's second leg. + int bytes_read = raw_transport1->pending_read_result(); + ASSERT_LT(0, bytes_read); + raw_transport1->pending_read_buf()->data()[bytes_read - 1]++; + + // Unblock the Finished message. |sock1->Read| should now fail. + raw_transport1->UnblockReadResult(); + EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, callback.GetResult(rv)); + + // Drop the old socket. This is needed because the Python test server can't + // service two sockets in parallel. + sock1.reset(); + + // Start a second connection. + scoped_ptr<StreamSocket> transport2( + new TCPClientSocket(addr(), &log_, NetLog::Source())); + EXPECT_EQ(OK, callback.GetResult(transport2->Connect(callback.callback()))); + scoped_ptr<SSLClientSocket> sock2 = CreateSSLClientSocket( + transport2.Pass(), test_server()->host_port_pair(), client_config); + EXPECT_EQ(OK, callback.GetResult(sock2->Connect(callback.callback()))); + + // No session resumption because the first connection never received a server + // Finished message. + SSLInfo ssl_info; + EXPECT_TRUE(sock2->GetSSLInfo(&ssl_info)); + EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, ssl_info.handshake_type); +} + // Connect to a server using channel id. It should allow the connection. TEST_F(SSLClientSocketChannelIDTest, SendChannelID) { SpawnedTestServer::SSLOptions ssl_options;
diff --git a/net/socket/ssl_session_cache_openssl.cc b/net/socket/ssl_session_cache_openssl.cc deleted file mode 100644 index 3e0879c..0000000 --- a/net/socket/ssl_session_cache_openssl.cc +++ /dev/null
@@ -1,509 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/socket/ssl_session_cache_openssl.h" - -#include <list> -#include <map> - -#include <openssl/rand.h> -#include <openssl/ssl.h> - -#include "base/containers/hash_tables.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/synchronization/lock.h" - -namespace net { - -namespace { - -// A helper class to lazily create a new EX_DATA index to map SSL_CTX handles -// to their corresponding SSLSessionCacheOpenSSLImpl object. -class SSLContextExIndex { -public: - SSLContextExIndex() { - context_index_ = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); - DCHECK_NE(-1, context_index_); - session_index_ = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL); - DCHECK_NE(-1, session_index_); - } - - int context_index() const { return context_index_; } - int session_index() const { return session_index_; } - - private: - int context_index_; - int session_index_; -}; - -// static -base::LazyInstance<SSLContextExIndex>::Leaky s_ssl_context_ex_instance = - LAZY_INSTANCE_INITIALIZER; - -// Retrieve the global EX_DATA index, created lazily on first call, to -// be used with SSL_CTX_set_ex_data() and SSL_CTX_get_ex_data(). -static int GetSSLContextExIndex() { - return s_ssl_context_ex_instance.Get().context_index(); -} - -// Retrieve the global EX_DATA index, created lazily on first call, to -// be used with SSL_SESSION_set_ex_data() and SSL_SESSION_get_ex_data(). -static int GetSSLSessionExIndex() { - return s_ssl_context_ex_instance.Get().session_index(); -} - -// Helper struct used to store session IDs in a SessionIdIndex container -// (see definition below). To save memory each entry only holds a pointer -// to the session ID buffer, which must outlive the entry itself. On the -// other hand, a hash is included to minimize the number of hashing -// computations during cache operations. -struct SessionId { - SessionId(const unsigned char* a_id, unsigned a_id_len) - : id(a_id), id_len(a_id_len), hash(ComputeHash(a_id, a_id_len)) {} - - explicit SessionId(const SessionId& other) - : id(other.id), id_len(other.id_len), hash(other.hash) {} - - explicit SessionId(SSL_SESSION* session) - : id(session->session_id), - id_len(session->session_id_length), - hash(ComputeHash(session->session_id, session->session_id_length)) {} - - bool operator==(const SessionId& other) const { - return hash == other.hash && id_len == other.id_len && - !memcmp(id, other.id, id_len); - } - - const unsigned char* id; - unsigned id_len; - size_t hash; - - private: - // Session ID are random strings of bytes. This happens to compute the same - // value as std::hash<std::string> without the extra string copy. See - // base/containers/hash_tables.h. Other hashing computations are possible, - // this one is just simple enough to do the job. - size_t ComputeHash(const unsigned char* id, unsigned id_len) { - size_t result = 0; - for (unsigned n = 0; n < id_len; ++n) { - result = (result * 131) + id[n]; - } - return result; - } -}; - -} // namespace - -} // namespace net - -namespace BASE_HASH_NAMESPACE { - -template <> -struct hash<net::SessionId> { - std::size_t operator()(const net::SessionId& entry) const { - return entry.hash; - } -}; - -} // namespace BASE_HASH_NAMESPACE - -namespace net { - -// Implementation of the real SSLSessionCache. -// -// The implementation is inspired by base::MRUCache, except that the deletor -// also needs to remove the entry from other containers. In a nutshell, this -// uses several basic containers: -// -// |ordering_| is a doubly-linked list of SSL_SESSION handles, ordered in -// MRU order. -// -// |key_index_| is a hash table mapping unique cache keys (e.g. host/port -// values) to a single iterator of |ordering_|. It is used to efficiently -// find the cached session associated with a given key. -// -// |id_index_| is a hash table mapping SessionId values to iterators -// of |key_index_|. If is used to efficiently remove sessions from the cache, -// as well as check for the existence of a session ID value in the cache. -// -// SSL_SESSION objects are reference-counted, and owned by the cache. This -// means that their reference count is incremented when they are added, and -// decremented when they are removed. -// -// Assuming an average key size of 100 characters, each node requires the -// following memory usage on 32-bit Android, when linked against STLport: -// -// 12 (ordering_ node, including SSL_SESSION handle) -// 100 (key characters) -// + 24 (std::string header/minimum size) -// + 8 (key_index_ node, excluding the 2 lines above for the key). -// + 20 (id_index_ node) -// -------- -// 164 bytes/node -// -// Hence, 41 KiB for a full cache with a maximum of 1024 entries, excluding -// the size of SSL_SESSION objects and heap fragmentation. -// - -class SSLSessionCacheOpenSSLImpl { - public: - // Construct new instance. This registers various hooks into the SSL_CTX - // context |ctx|. OpenSSL will call back during SSL connection - // operations. |key_func| is used to map a SSL handle to a unique cache - // string, according to the client's preferences. - SSLSessionCacheOpenSSLImpl(SSL_CTX* ctx, - const SSLSessionCacheOpenSSL::Config& config) - : ctx_(ctx), config_(config), expiration_check_(0) { - DCHECK(ctx); - - // NO_INTERNAL_STORE disables OpenSSL's builtin cache, and - // NO_AUTO_CLEAR disables the call to SSL_CTX_flush_sessions - // every 256 connections (this number is hard-coded in the library - // and can't be changed). - SSL_CTX_set_session_cache_mode(ctx_, - SSL_SESS_CACHE_CLIENT | - SSL_SESS_CACHE_NO_INTERNAL_STORE | - SSL_SESS_CACHE_NO_AUTO_CLEAR); - - SSL_CTX_sess_set_new_cb(ctx_, NewSessionCallbackStatic); - SSL_CTX_sess_set_remove_cb(ctx_, RemoveSessionCallbackStatic); - SSL_CTX_set_generate_session_id(ctx_, GenerateSessionIdStatic); - SSL_CTX_set_timeout(ctx_, config_.timeout_seconds); - - SSL_CTX_set_ex_data(ctx_, GetSSLContextExIndex(), this); - } - - // Destroy this instance. Must happen before |ctx_| is destroyed. - ~SSLSessionCacheOpenSSLImpl() { - Flush(); - SSL_CTX_set_ex_data(ctx_, GetSSLContextExIndex(), NULL); - SSL_CTX_sess_set_new_cb(ctx_, NULL); - SSL_CTX_sess_set_remove_cb(ctx_, NULL); - SSL_CTX_set_generate_session_id(ctx_, NULL); - } - - // Return the number of items in this cache. - size_t size() const { return key_index_.size(); } - - // Retrieve the cache key from |ssl| and look for a corresponding - // cached session ID. If one is found, call SSL_set_session() to associate - // it with the |ssl| connection. - // - // Will also check for expired sessions every |expiration_check_count| - // calls. - // - // Return true if a cached session ID was found, false otherwise. - bool SetSSLSession(SSL* ssl) { - std::string cache_key = config_.key_func(ssl); - if (cache_key.empty()) - return false; - - return SetSSLSessionWithKey(ssl, cache_key); - } - - // Variant of SetSSLSession to be used when the client already has computed - // the cache key. Avoid a call to the configuration's |key_func| function. - bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key) { - base::AutoLock locked(lock_); - - DCHECK_EQ(config_.key_func(ssl), cache_key); - - if (++expiration_check_ >= config_.expiration_check_count) { - expiration_check_ = 0; - FlushExpiredSessionsLocked(); - } - - KeyIndex::iterator it = key_index_.find(cache_key); - if (it == key_index_.end()) - return false; - - SSL_SESSION* session = *it->second; - DCHECK(session); - - DVLOG(2) << "Lookup session: " << session << " for " << cache_key; - - void* session_is_good = - SSL_SESSION_get_ex_data(session, GetSSLSessionExIndex()); - if (!session_is_good) - return false; // Session has not yet been marked good. Treat as a miss. - - // Move to front of MRU list. - ordering_.push_front(session); - ordering_.erase(it->second); - it->second = ordering_.begin(); - - return SSL_set_session(ssl, session) == 1; - } - - void MarkSSLSessionAsGood(SSL* ssl) { - SSL_SESSION* session = SSL_get_session(ssl); - if (!session) - return; - - // Mark the session as good, allowing it to be used for future connections. - SSL_SESSION_set_ex_data( - session, GetSSLSessionExIndex(), reinterpret_cast<void*>(1)); - } - - // Flush all entries from the cache. - void Flush() { - base::AutoLock lock(lock_); - id_index_.clear(); - key_index_.clear(); - while (!ordering_.empty()) { - SSL_SESSION* session = ordering_.front(); - ordering_.pop_front(); - SSL_SESSION_free(session); - } - } - - private: - // Type for list of SSL_SESSION handles, ordered in MRU order. - typedef std::list<SSL_SESSION*> MRUSessionList; - // Type for a dictionary from unique cache keys to session list nodes. - typedef base::hash_map<std::string, MRUSessionList::iterator> KeyIndex; - // Type for a dictionary from SessionId values to key index nodes. - typedef base::hash_map<SessionId, KeyIndex::iterator> SessionIdIndex; - - // Return the key associated with a given session, or the empty string if - // none exist. This shall only be used for debugging. - std::string SessionKey(SSL_SESSION* session) { - if (!session) - return std::string("<null-session>"); - - if (session->session_id_length == 0) - return std::string("<empty-session-id>"); - - SessionIdIndex::iterator it = id_index_.find(SessionId(session)); - if (it == id_index_.end()) - return std::string("<unknown-session>"); - - return it->second->first; - } - - // Remove a given |session| from the cache. Lock must be held. - void RemoveSessionLocked(SSL_SESSION* session) { - lock_.AssertAcquired(); - DCHECK(session); - DCHECK_GT(session->session_id_length, 0U); - SessionId session_id(session); - SessionIdIndex::iterator id_it = id_index_.find(session_id); - if (id_it == id_index_.end()) { - LOG(ERROR) << "Trying to remove unknown session from cache: " << session; - return; - } - KeyIndex::iterator key_it = id_it->second; - DCHECK(key_it != key_index_.end()); - DCHECK_EQ(session, *key_it->second); - - id_index_.erase(session_id); - ordering_.erase(key_it->second); - key_index_.erase(key_it); - - SSL_SESSION_free(session); - - DCHECK_EQ(key_index_.size(), id_index_.size()); - } - - // Used internally to flush expired sessions. Lock must be held. - void FlushExpiredSessionsLocked() { - lock_.AssertAcquired(); - - // Unfortunately, OpenSSL initializes |session->time| with a time() - // timestamps, which makes mocking / unit testing difficult. - long timeout_secs = static_cast<long>(::time(NULL)); - MRUSessionList::iterator it = ordering_.begin(); - while (it != ordering_.end()) { - SSL_SESSION* session = *it++; - - // Important, use <= instead of < here to allow unit testing to - // work properly. That's because unit tests that check the expiration - // behaviour will use a session timeout of 0 seconds. - if (session->time + session->timeout <= timeout_secs) { - DVLOG(2) << "Expiring session " << session << " for " - << SessionKey(session); - RemoveSessionLocked(session); - } - } - } - - // Retrieve the cache associated with a given SSL context |ctx|. - static SSLSessionCacheOpenSSLImpl* GetCache(SSL_CTX* ctx) { - DCHECK(ctx); - void* result = SSL_CTX_get_ex_data(ctx, GetSSLContextExIndex()); - DCHECK(result); - return reinterpret_cast<SSLSessionCacheOpenSSLImpl*>(result); - } - - // Called by OpenSSL when a new |session| was created and added to a given - // |ssl| connection. Note that the session's reference count was already - // incremented before the function is entered. The function must return 1 - // to indicate that it took ownership of the session, i.e. that the caller - // should not decrement its reference count after completion. - static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { - GetCache(ssl->ctx)->OnSessionAdded(ssl, session); - return 1; - } - - // Called by OpenSSL to indicate that a session must be removed from the - // cache. This happens when SSL_CTX is destroyed. - static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { - GetCache(ctx)->OnSessionRemoved(session); - } - - // Called by OpenSSL to generate a new session ID. This happens during a - // SSL connection operation, when the SSL object doesn't have a session yet. - // - // A session ID is a random string of bytes used to uniquely identify the - // session between a client and a server. - // - // |ssl| is a SSL connection handle. Ignored here. - // |id| is the target buffer where the ID must be generated. - // |*id_len| is, on input, the size of the desired ID. It will be 16 for - // SSLv2, and 32 for anything else. OpenSSL allows an implementation - // to change it on output, but this will not happen here. - // - // The function must ensure the generated ID is really unique, i.e. that - // another session in the cache doesn't already use the same value. It must - // return 1 to indicate success, or 0 for failure. - static int GenerateSessionIdStatic(const SSL* ssl, - unsigned char* id, - unsigned* id_len) { - if (!GetCache(ssl->ctx)->OnGenerateSessionId(id, *id_len)) - return 0; - - return 1; - } - - // Add |session| to the cache in association with |cache_key|. If a session - // already exists, it is replaced with the new one. This assumes that the - // caller already incremented the session's reference count. - void OnSessionAdded(SSL* ssl, SSL_SESSION* session) { - base::AutoLock locked(lock_); - DCHECK(ssl); - DCHECK_GT(session->session_id_length, 0U); - std::string cache_key = config_.key_func(ssl); - KeyIndex::iterator it = key_index_.find(cache_key); - if (it == key_index_.end()) { - DVLOG(2) << "Add session " << session << " for " << cache_key; - // This is a new session. Add it to the cache. - ordering_.push_front(session); - std::pair<KeyIndex::iterator, bool> ret = - key_index_.insert(std::make_pair(cache_key, ordering_.begin())); - DCHECK(ret.second); - it = ret.first; - DCHECK(it != key_index_.end()); - } else { - // An existing session exists for this key, so replace it if needed. - DVLOG(2) << "Replace session " << *it->second << " with " << session - << " for " << cache_key; - SSL_SESSION* old_session = *it->second; - if (old_session != session) { - id_index_.erase(SessionId(old_session)); - SSL_SESSION_free(old_session); - } - ordering_.erase(it->second); - ordering_.push_front(session); - it->second = ordering_.begin(); - } - - id_index_[SessionId(session)] = it; - - if (key_index_.size() > config_.max_entries) - ShrinkCacheLocked(); - - DCHECK_EQ(key_index_.size(), id_index_.size()); - DCHECK_LE(key_index_.size(), config_.max_entries); - } - - // Shrink the cache to ensure no more than config_.max_entries entries, - // starting with older entries first. Lock must be acquired. - void ShrinkCacheLocked() { - lock_.AssertAcquired(); - DCHECK_EQ(key_index_.size(), ordering_.size()); - DCHECK_EQ(key_index_.size(), id_index_.size()); - - while (key_index_.size() > config_.max_entries) { - MRUSessionList::reverse_iterator it = ordering_.rbegin(); - DCHECK(it != ordering_.rend()); - - SSL_SESSION* session = *it; - DCHECK(session); - DVLOG(2) << "Evicting session " << session << " for " - << SessionKey(session); - RemoveSessionLocked(session); - } - } - - // Remove |session| from the cache. - void OnSessionRemoved(SSL_SESSION* session) { - base::AutoLock locked(lock_); - DVLOG(2) << "Remove session " << session << " for " << SessionKey(session); - RemoveSessionLocked(session); - } - - // See GenerateSessionIdStatic for a description of what this function does. - bool OnGenerateSessionId(unsigned char* id, unsigned id_len) { - base::AutoLock locked(lock_); - // This mimics def_generate_session_id() in openssl/ssl/ssl_sess.cc, - // I.e. try to generate a pseudo-random bit string, and check that no - // other entry in the cache has the same value. - const size_t kMaxTries = 10; - for (size_t tries = 0; tries < kMaxTries; ++tries) { - if (RAND_pseudo_bytes(id, id_len) <= 0) { - DLOG(ERROR) << "Couldn't generate " << id_len - << " pseudo random bytes?"; - return false; - } - if (id_index_.find(SessionId(id, id_len)) == id_index_.end()) - return true; - } - DLOG(ERROR) << "Couldn't generate unique session ID of " << id_len - << "bytes after " << kMaxTries << " tries."; - return false; - } - - SSL_CTX* ctx_; - SSLSessionCacheOpenSSL::Config config_; - - // method to get the index which can later be used with SSL_CTX_get_ex_data() - // or SSL_CTX_set_ex_data(). - base::Lock lock_; // Protects access to containers below. - - MRUSessionList ordering_; - KeyIndex key_index_; - SessionIdIndex id_index_; - - size_t expiration_check_; -}; - -SSLSessionCacheOpenSSL::~SSLSessionCacheOpenSSL() { delete impl_; } - -size_t SSLSessionCacheOpenSSL::size() const { return impl_->size(); } - -void SSLSessionCacheOpenSSL::Reset(SSL_CTX* ctx, const Config& config) { - if (impl_) - delete impl_; - - impl_ = new SSLSessionCacheOpenSSLImpl(ctx, config); -} - -bool SSLSessionCacheOpenSSL::SetSSLSession(SSL* ssl) { - return impl_->SetSSLSession(ssl); -} - -bool SSLSessionCacheOpenSSL::SetSSLSessionWithKey( - SSL* ssl, - const std::string& cache_key) { - return impl_->SetSSLSessionWithKey(ssl, cache_key); -} - -void SSLSessionCacheOpenSSL::MarkSSLSessionAsGood(SSL* ssl) { - return impl_->MarkSSLSessionAsGood(ssl); -} - -void SSLSessionCacheOpenSSL::Flush() { impl_->Flush(); } - -} // namespace net
diff --git a/net/socket/ssl_session_cache_openssl.h b/net/socket/ssl_session_cache_openssl.h deleted file mode 100644 index bbd96596..0000000 --- a/net/socket/ssl_session_cache_openssl.h +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H -#define NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H - -#include <string> - -#include "base/basictypes.h" -#include "net/base/net_export.h" - -// Avoid including OpenSSL headers here. -typedef struct ssl_ctx_st SSL_CTX; -typedef struct ssl_st SSL; - -namespace net { - -class SSLSessionCacheOpenSSLImpl; - -// A class used to implement a custom cache of SSL_SESSION objects. -// Usage is as follows: -// -// - Client creates a new cache instance with appropriate configuration, -// associating it with a given SSL_CTX object. -// -// The configuration must include a pointer to a client-provided function -// that can retrieve a unique cache key from an existing SSL handle. -// -// - When creating a new SSL connection, call SetSSLSession() with the newly -// created SSL handle, and a cache key for the current host/port. If a -// session is already in the cache, it will be added to the connection -// through SSL_set_session(). -// -// - Otherwise, OpenSSL will create a new SSL_SESSION object during the -// connection, and will pass it to the cache's internal functions, -// transparently to the client. -// -// - Each session has a timeout in seconds, which are checked every N-th call -// to SetSSLSession(), where N is the current configuration's -// |check_expiration_count|. Expired sessions are removed automatically -// from the cache. -// -// - Clients can call Flush() to remove all sessions from the cache, this is -// useful when the system's certificate store has changed. -// -// This class is thread-safe. There shouldn't be any issue with multiple -// SSL connections being performed in parallel in multiple threads. -class NET_EXPORT SSLSessionCacheOpenSSL { - public: - // Type of a function that takes a SSL handle and returns a unique cache - // key string to identify it. - typedef std::string GetSessionKeyFunction(const SSL* ssl); - - // A small structure used to configure a cache on creation. - // |key_func| is a function used at runtime to retrieve the unique cache key - // from a given SSL connection handle. - // |max_entries| is the maximum number of entries in the cache. - // |expiration_check_count| is the number of calls to SetSSLSession() that - // will trigger a check for expired sessions. - // |timeout_seconds| is the timeout of new cached sessions in seconds. - struct Config { - GetSessionKeyFunction* key_func; - size_t max_entries; - size_t expiration_check_count; - int timeout_seconds; - }; - - SSLSessionCacheOpenSSL() : impl_(NULL) {} - - // Construct a new cache instance. - // |ctx| is a SSL_CTX context handle that will be associated with this cache. - // |key_func| is a function that will be used at runtime to retrieve the - // unique cache key from a SSL connection handle. - // |max_entries| is the maximum number of entries in the cache. - // |timeout_seconds| is the timeout of new cached sessions in seconds. - // |expiration_check_count| is the number of calls to SetSSLSession() that - // will trigger a check for expired sessions. - SSLSessionCacheOpenSSL(SSL_CTX* ctx, const Config& config) : impl_(NULL) { - Reset(ctx, config); - } - - // Destroy this instance. This must be called before the SSL_CTX handle - // is destroyed. - ~SSLSessionCacheOpenSSL(); - - // Reset the cache configuration. This flushes any existing entries. - void Reset(SSL_CTX* ctx, const Config& config); - - size_t size() const; - - // Lookup the unique cache key associated with |ssl| connection handle, - // and find a cached session for it in the cache. If one is found, associate - // it with the |ssl| connection through SSL_set_session(). Consider using - // SetSSLSessionWithKey() if you already have the key. - // - // Every |check_expiration_count| call to either SetSSLSession() or - // SetSSLSessionWithKey() triggers a check for, and removal of, expired - // sessions. - // - // Return true iff a cached session was associated with the |ssl| connection. - bool SetSSLSession(SSL* ssl); - - // A more efficient variant of SetSSLSession() that can be used if the caller - // already has the cache key for the session of interest. The caller must - // ensure that the value of |cache_key| matches the result of calling the - // configuration's |key_func| function with the |ssl| as parameter. - // - // Every |check_expiration_count| call to either SetSSLSession() or - // SetSSLSessionWithKey() triggers a check for, and removal of, expired - // sessions. - // - // Return true iff a cached session was associated with the |ssl| connection. - bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key); - - // Indicates that the SSL session associated with |ssl| is "good" - that is, - // that all associated cryptographic parameters that were negotiated, - // including the peer's certificate, were successfully validated. Because - // OpenSSL does not provide an asynchronous certificate verification - // callback, it's necessary to manually manage the sessions to ensure that - // only validated sessions are resumed. - void MarkSSLSessionAsGood(SSL* ssl); - - // Flush removes all entries from the cache. This is typically called when - // the system's certificate store has changed. - void Flush(); - - // TODO(digit): Move to client code. - static const int kDefaultTimeoutSeconds = 60 * 60; - static const size_t kMaxEntries = 1024; - static const size_t kMaxExpirationChecks = 256; - - private: - DISALLOW_COPY_AND_ASSIGN(SSLSessionCacheOpenSSL); - - SSLSessionCacheOpenSSLImpl* impl_; -}; - -} // namespace net - -#endif // NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
diff --git a/net/socket/ssl_session_cache_openssl_unittest.cc b/net/socket/ssl_session_cache_openssl_unittest.cc deleted file mode 100644 index 21e7564..0000000 --- a/net/socket/ssl_session_cache_openssl_unittest.cc +++ /dev/null
@@ -1,378 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/socket/ssl_session_cache_openssl.h" - -#include <openssl/ssl.h> - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" -#include "net/ssl/scoped_openssl_types.h" - -#include "testing/gtest/include/gtest/gtest.h" - -// This is an internal OpenSSL function that can be used to create a new -// session for an existing SSL object. This shall force a call to the -// 'generate_session_id' callback from the SSL's session context. -// |s| is the target SSL connection handle. -// |session| is non-0 to ask for the creation of a new session. If 0, -// this will set an empty session with no ID instead. -extern "C" OPENSSL_EXPORT int ssl_get_new_session(SSL* s, int session); - -// This is an internal OpenSSL function which is used internally to add -// a new session to the cache. It is normally triggered by a succesful -// connection. However, this unit test does not use the network at all. -extern "C" OPENSSL_EXPORT void ssl_update_cache(SSL* s, int mode); - -namespace net { - -namespace { - -// Helper class used to associate arbitrary std::string keys with SSL objects. -class SSLKeyHelper { - public: - // Return the string associated with a given SSL handle |ssl|, or the - // empty string if none exists. - static std::string Get(const SSL* ssl) { - return GetInstance()->GetValue(ssl); - } - - // Associate a string with a given SSL handle |ssl|. - static void Set(SSL* ssl, const std::string& value) { - GetInstance()->SetValue(ssl, value); - } - - static SSLKeyHelper* GetInstance() { - static base::LazyInstance<SSLKeyHelper>::Leaky s_instance = - LAZY_INSTANCE_INITIALIZER; - return s_instance.Pointer(); - } - - SSLKeyHelper() { - ex_index_ = SSL_get_ex_new_index(0, NULL, NULL, KeyDup, KeyFree); - CHECK_NE(-1, ex_index_); - } - - std::string GetValue(const SSL* ssl) { - std::string* value = - reinterpret_cast<std::string*>(SSL_get_ex_data(ssl, ex_index_)); - if (!value) - return std::string(); - return *value; - } - - void SetValue(SSL* ssl, const std::string& value) { - int ret = SSL_set_ex_data(ssl, ex_index_, new std::string(value)); - CHECK_EQ(1, ret); - } - - // Called when an SSL object is copied through SSL_dup(). This needs to copy - // the value as well. - static int KeyDup(CRYPTO_EX_DATA* to, - const CRYPTO_EX_DATA* from, - void** from_fd, - int idx, - long argl, - void* argp) { - // |from_fd| is really the address of a temporary pointer. On input, it - // points to the value from the original SSL object. The function must - // update it to the address of a copy. - std::string** ptr = reinterpret_cast<std::string**>(from_fd); - std::string* old_string = *ptr; - std::string* new_string = new std::string(*old_string); - *ptr = new_string; - return 0; // Ignored by the implementation. - } - - // Called to destroy the value associated with an SSL object. - static void KeyFree(void* parent, - void* ptr, - CRYPTO_EX_DATA* ad, - int index, - long argl, - void* argp) { - std::string* value = reinterpret_cast<std::string*>(ptr); - delete value; - } - - int ex_index_; -}; - -} // namespace - -class SSLSessionCacheOpenSSLTest : public testing::Test { - public: - SSLSessionCacheOpenSSLTest() { - crypto::EnsureOpenSSLInit(); - ctx_.reset(SSL_CTX_new(SSLv23_client_method())); - cache_.Reset(ctx_.get(), kDefaultConfig); - } - - // Reset cache configuration. - void ResetConfig(const SSLSessionCacheOpenSSL::Config& config) { - cache_.Reset(ctx_.get(), config); - } - - // Helper function to create a new SSL connection object associated with - // a given unique |cache_key|. This does _not_ add the session to the cache. - // Caller must free the object with SSL_free(). - SSL* NewSSL(const std::string& cache_key) { - SSL* ssl = SSL_new(ctx_.get()); - if (!ssl) - return NULL; - - SSLKeyHelper::Set(ssl, cache_key); // associate cache key. - ResetSessionID(ssl); // create new unique session ID. - return ssl; - } - - // Reset the session ID of a given SSL object. This creates a new session - // with a new unique random ID. Does not add it to the cache. - static void ResetSessionID(SSL* ssl) { ssl_get_new_session(ssl, 1); } - - // Add a given SSL object and its session to the cache. - void AddToCache(SSL* ssl) { - ssl_update_cache(ssl, ctx_.get()->session_cache_mode); - } - - static const SSLSessionCacheOpenSSL::Config kDefaultConfig; - - protected: - ScopedSSL_CTX ctx_; - // |cache_| must be destroyed before |ctx_| and thus appears after it. - SSLSessionCacheOpenSSL cache_; -}; - -// static -const SSLSessionCacheOpenSSL::Config - SSLSessionCacheOpenSSLTest::kDefaultConfig = { - &SSLKeyHelper::Get, // key_func - 1024, // max_entries - 256, // expiration_check_count - 60 * 60, // timeout_seconds -}; - -TEST_F(SSLSessionCacheOpenSSLTest, EmptyCacheCreation) { - EXPECT_EQ(0U, cache_.size()); -} - -TEST_F(SSLSessionCacheOpenSSLTest, CacheOneSession) { - ScopedSSL ssl(NewSSL("hello")); - - EXPECT_EQ(0U, cache_.size()); - AddToCache(ssl.get()); - EXPECT_EQ(1U, cache_.size()); - ssl.reset(NULL); - EXPECT_EQ(1U, cache_.size()); -} - -TEST_F(SSLSessionCacheOpenSSLTest, CacheMultipleSessions) { - const size_t kNumItems = 100; - int local_id = 1; - - // Add kNumItems to the cache. - for (size_t n = 0; n < kNumItems; ++n) { - std::string local_id_string = base::StringPrintf("%d", local_id++); - ScopedSSL ssl(NewSSL(local_id_string)); - AddToCache(ssl.get()); - EXPECT_EQ(n + 1, cache_.size()); - } -} - -TEST_F(SSLSessionCacheOpenSSLTest, Flush) { - const size_t kNumItems = 100; - int local_id = 1; - - // Add kNumItems to the cache. - for (size_t n = 0; n < kNumItems; ++n) { - std::string local_id_string = base::StringPrintf("%d", local_id++); - ScopedSSL ssl(NewSSL(local_id_string)); - AddToCache(ssl.get()); - } - EXPECT_EQ(kNumItems, cache_.size()); - - cache_.Flush(); - EXPECT_EQ(0U, cache_.size()); -} - -TEST_F(SSLSessionCacheOpenSSLTest, SetSSLSession) { - const std::string key("hello"); - ScopedSSL ssl(NewSSL(key)); - - // First call should fail because the session is not in the cache. - EXPECT_FALSE(cache_.SetSSLSession(ssl.get())); - SSL_SESSION* session = ssl.get()->session; - EXPECT_TRUE(session); - EXPECT_EQ(1, session->references); - - AddToCache(ssl.get()); - EXPECT_EQ(2, session->references); - - // Mark the session as good, so that it is re-used for the second connection. - cache_.MarkSSLSessionAsGood(ssl.get()); - - ssl.reset(NULL); - EXPECT_EQ(1, session->references); - - // Second call should find the session ID and associate it with |ssl2|. - ScopedSSL ssl2(NewSSL(key)); - EXPECT_TRUE(cache_.SetSSLSession(ssl2.get())); - - EXPECT_EQ(session, ssl2.get()->session); - EXPECT_EQ(2, session->references); -} - -TEST_F(SSLSessionCacheOpenSSLTest, SetSSLSessionWithKey) { - const std::string key("hello"); - ScopedSSL ssl(NewSSL(key)); - AddToCache(ssl.get()); - cache_.MarkSSLSessionAsGood(ssl.get()); - ssl.reset(NULL); - - ScopedSSL ssl2(NewSSL(key)); - EXPECT_TRUE(cache_.SetSSLSessionWithKey(ssl2.get(), key)); -} - -TEST_F(SSLSessionCacheOpenSSLTest, CheckSessionReplacement) { - // Check that if two SSL connections have the same key, only one - // corresponding session can be stored in the cache. - const std::string common_key("common-key"); - ScopedSSL ssl1(NewSSL(common_key)); - ScopedSSL ssl2(NewSSL(common_key)); - - AddToCache(ssl1.get()); - EXPECT_EQ(1U, cache_.size()); - EXPECT_EQ(2, ssl1.get()->session->references); - - // This ends up calling OnSessionAdded which will discover that there is - // already one session ID associated with the key, and will replace it. - AddToCache(ssl2.get()); - EXPECT_EQ(1U, cache_.size()); - EXPECT_EQ(1, ssl1.get()->session->references); - EXPECT_EQ(2, ssl2.get()->session->references); -} - -// Check that when two connections have the same key, a new session is created -// if the existing session has not yet been marked "good". Further, after the -// first session completes, if the second session has replaced it in the cache, -// new sessions should continue to fail until the currently cached session -// succeeds. -TEST_F(SSLSessionCacheOpenSSLTest, CheckSessionReplacementWhenNotGood) { - const std::string key("hello"); - ScopedSSL ssl(NewSSL(key)); - - // First call should fail because the session is not in the cache. - EXPECT_FALSE(cache_.SetSSLSession(ssl.get())); - SSL_SESSION* session = ssl.get()->session; - ASSERT_TRUE(session); - EXPECT_EQ(1, session->references); - - AddToCache(ssl.get()); - EXPECT_EQ(2, session->references); - - // Second call should find the session ID, but because it is not yet good, - // fail to associate it with |ssl2|. - ScopedSSL ssl2(NewSSL(key)); - EXPECT_FALSE(cache_.SetSSLSession(ssl2.get())); - SSL_SESSION* session2 = ssl2.get()->session; - ASSERT_TRUE(session2); - EXPECT_EQ(1, session2->references); - - EXPECT_NE(session, session2); - - // Add the second connection to the cache. It should replace the first - // session, and the cache should hold on to the second session. - AddToCache(ssl2.get()); - EXPECT_EQ(1, session->references); - EXPECT_EQ(2, session2->references); - - // Mark the first session as good, simulating it completing. - cache_.MarkSSLSessionAsGood(ssl.get()); - - // Third call should find the session ID, but because the second session (the - // current cache entry) is not yet good, fail to associate it with |ssl3|. - ScopedSSL ssl3(NewSSL(key)); - EXPECT_FALSE(cache_.SetSSLSession(ssl3.get())); - EXPECT_NE(session, ssl3.get()->session); - EXPECT_NE(session2, ssl3.get()->session); - EXPECT_EQ(1, ssl3.get()->session->references); -} - -TEST_F(SSLSessionCacheOpenSSLTest, CheckEviction) { - const size_t kMaxItems = 20; - int local_id = 1; - - SSLSessionCacheOpenSSL::Config config = kDefaultConfig; - config.max_entries = kMaxItems; - ResetConfig(config); - - // Add kMaxItems to the cache. - for (size_t n = 0; n < kMaxItems; ++n) { - std::string local_id_string = base::StringPrintf("%d", local_id++); - ScopedSSL ssl(NewSSL(local_id_string)); - - AddToCache(ssl.get()); - EXPECT_EQ(n + 1, cache_.size()); - } - - // Continue adding new items to the cache, check that old ones are - // evicted. - for (size_t n = 0; n < kMaxItems; ++n) { - std::string local_id_string = base::StringPrintf("%d", local_id++); - ScopedSSL ssl(NewSSL(local_id_string)); - - AddToCache(ssl.get()); - EXPECT_EQ(kMaxItems, cache_.size()); - } -} - -// Check that session expiration works properly. -TEST_F(SSLSessionCacheOpenSSLTest, CheckExpiration) { - const size_t kMaxCheckCount = 10; - const size_t kNumEntries = 20; - - SSLSessionCacheOpenSSL::Config config = kDefaultConfig; - config.expiration_check_count = kMaxCheckCount; - config.timeout_seconds = 1000; - ResetConfig(config); - - // Add |kNumItems - 1| session entries with crafted time values. - for (size_t n = 0; n < kNumEntries - 1U; ++n) { - std::string key = base::StringPrintf("%d", static_cast<int>(n)); - ScopedSSL ssl(NewSSL(key)); - // Cheat a little: Force the session |time| value, this guarantees that they - // are expired, given that ::time() will always return a value that is - // past the first 100 seconds after the Unix epoch. - ssl.get()->session->time = static_cast<long>(n); - AddToCache(ssl.get()); - } - EXPECT_EQ(kNumEntries - 1U, cache_.size()); - - // Add nother session which will get the current time, and thus not be - // expirable until 1000 seconds have passed. - ScopedSSL good_ssl(NewSSL("good-key")); - AddToCache(good_ssl.get()); - good_ssl.reset(NULL); - EXPECT_EQ(kNumEntries, cache_.size()); - - // Call SetSSLSession() |kMaxCheckCount - 1| times, this shall not expire - // any session - for (size_t n = 0; n < kMaxCheckCount - 1U; ++n) { - ScopedSSL ssl(NewSSL("unknown-key")); - cache_.SetSSLSession(ssl.get()); - EXPECT_EQ(kNumEntries, cache_.size()); - } - - // Call SetSSLSession another time, this shall expire all sessions except - // the last one. - ScopedSSL bad_ssl(NewSSL("unknown-key")); - cache_.SetSSLSession(bad_ssl.get()); - bad_ssl.reset(NULL); - EXPECT_EQ(1U, cache_.size()); -} - -} // namespace net
diff --git a/net/socket/tcp_socket_libevent.cc b/net/socket/tcp_socket_libevent.cc index c5d30e1d..56c19b20 100644 --- a/net/socket/tcp_socket_libevent.cc +++ b/net/socket/tcp_socket_libevent.cc
@@ -56,6 +56,7 @@ // SetTCPKeepAlive sets SO_KEEPALIVE. bool SetTCPKeepAlive(int fd, bool enable, int delay) { + // Enabling TCP keepalives is the same on all platforms. int on = enable ? 1 : 0; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on))) { PLOG(ERROR) << "Failed to set SO_KEEPALIVE on fd: " << fd; @@ -67,6 +68,8 @@ return true; #if defined(OS_LINUX) || defined(OS_ANDROID) + // Setting the keepalive interval varies by platform. + // Set seconds until first TCP keep alive. if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &delay, sizeof(delay))) { PLOG(ERROR) << "Failed to set TCP_KEEPIDLE on fd: " << fd; @@ -77,6 +80,11 @@ PLOG(ERROR) << "Failed to set TCP_KEEPINTVL on fd: " << fd; return false; } +#elif defined(OS_MACOSX) || defined(OS_IOS) + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay))) { + PLOG(ERROR) << "Failed to set TCP_KEEPALIVE on fd: " << fd; + return false; + } #endif return true; }
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 3be92e3..d5a395bd 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -2960,8 +2960,6 @@ base::TimeDelta delay = hung_interval_ - (now - last_activity_time_); if (delay.InMilliseconds() < 0 || last_activity_time_ < last_check_time) { - // Track all failed PING messages in a separate bucket. - RecordPingRTTHistogram(base::TimeDelta::Max()); DoDrainSession(ERR_SPDY_PING_FAILED, "Failed ping."); return; } @@ -2975,7 +2973,9 @@ } void SpdySession::RecordPingRTTHistogram(base::TimeDelta duration) { - UMA_HISTOGRAM_TIMES("Net.SpdyPing.RTT", duration); + UMA_HISTOGRAM_CUSTOM_TIMES("Net.SpdyPing.RTT", duration, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(10), 100); } void SpdySession::RecordProtocolErrorHistogram(
diff --git a/net/ssl/scoped_openssl_types.h b/net/ssl/scoped_openssl_types.h index 8bbdbd5..a8c3c34 100644 --- a/net/ssl/scoped_openssl_types.h +++ b/net/ssl/scoped_openssl_types.h
@@ -16,6 +16,7 @@ crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>; using ScopedSSL = crypto::ScopedOpenSSL<SSL, SSL_free>; using ScopedSSL_CTX = crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free>; +using ScopedSSL_SESSION = crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free>; using ScopedX509 = crypto::ScopedOpenSSL<X509, X509_free>; } // namespace net
diff --git a/net/ssl/ssl_client_session_cache_openssl.cc b/net/ssl/ssl_client_session_cache_openssl.cc new file mode 100644 index 0000000..4f67b97 --- /dev/null +++ b/net/ssl/ssl_client_session_cache_openssl.cc
@@ -0,0 +1,107 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ssl/ssl_client_session_cache_openssl.h" + +#include <utility> + +#include "base/logging.h" +#include "base/time/clock.h" +#include "base/time/default_clock.h" + +namespace net { + +SSLClientSessionCacheOpenSSL::SSLClientSessionCacheOpenSSL(const Config& config) + : clock_(new base::DefaultClock), + config_(config), + cache_(config.max_entries), + lookups_since_flush_(0) { +} + +SSLClientSessionCacheOpenSSL::~SSLClientSessionCacheOpenSSL() { + // TODO(davidben): The session cache is currently a singleton, so it is + // destroyed on a different thread than the one it's created on. When + // https://crbug.com/458365 is fixed, this will no longer be an issue. + thread_checker_.DetachFromThread(); + + Flush(); +} + +size_t SSLClientSessionCacheOpenSSL::size() const { + return cache_.size(); +} + +SSL_SESSION* SSLClientSessionCacheOpenSSL::Lookup( + const std::string& cache_key) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // Expire stale sessions. + lookups_since_flush_++; + if (lookups_since_flush_ >= config_.expiration_check_count) { + lookups_since_flush_ = 0; + FlushExpiredSessions(); + } + + CacheEntryMap::iterator iter = cache_.Get(cache_key); + if (iter == cache_.end()) + return nullptr; + if (IsExpired(iter->second, clock_->Now())) { + cache_.Erase(iter); + return nullptr; + } + return iter->second->session.get(); +} + +void SSLClientSessionCacheOpenSSL::Insert(const std::string& cache_key, + SSL_SESSION* session) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // Make a new entry. + CacheEntry* entry = new CacheEntry; + entry->session.reset(SSL_SESSION_up_ref(session)); + entry->creation_time = clock_->Now(); + + // Takes ownership. + cache_.Put(cache_key, entry); +} + +void SSLClientSessionCacheOpenSSL::Flush() { + DCHECK(thread_checker_.CalledOnValidThread()); + + cache_.Clear(); +} + +void SSLClientSessionCacheOpenSSL::SetClockForTesting( + scoped_ptr<base::Clock> clock) { + DCHECK(thread_checker_.CalledOnValidThread()); + + clock_ = clock.Pass(); +} + +SSLClientSessionCacheOpenSSL::CacheEntry::CacheEntry() { +} + +SSLClientSessionCacheOpenSSL::CacheEntry::~CacheEntry() { +} + +bool SSLClientSessionCacheOpenSSL::IsExpired( + SSLClientSessionCacheOpenSSL::CacheEntry* entry, + const base::Time& now) { + return now < entry->creation_time || + entry->creation_time + config_.timeout < now; +} + +void SSLClientSessionCacheOpenSSL::FlushExpiredSessions() { + base::Time now = clock_->Now(); + CacheEntryMap::iterator iter = cache_.begin(); + while (iter != cache_.end()) { + if (IsExpired(iter->second, now)) { + iter = cache_.Erase(iter); + } else { + ++iter; + } + } +} + +} // namespace net
diff --git a/net/ssl/ssl_client_session_cache_openssl.h b/net/ssl/ssl_client_session_cache_openssl.h new file mode 100644 index 0000000..bfe912b --- /dev/null +++ b/net/ssl/ssl_client_session_cache_openssl.h
@@ -0,0 +1,92 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SSL_SSL_CLIENT_SESSION_CACHE_OPENSSL_H +#define NET_SSL_SSL_CLIENT_SESSION_CACHE_OPENSSL_H + +#include <openssl/ssl.h> + +#include <string> + +#include "base/containers/mru_cache.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/thread_checker.h" +#include "base/time/time.h" +#include "net/base/net_export.h" +#include "net/ssl/scoped_openssl_types.h" + +namespace base { +class Clock; +} + +namespace net { + +class NET_EXPORT SSLClientSessionCacheOpenSSL { + public: + struct Config { + // The maximum number of entries in the cache. + size_t max_entries = 1024; + // The number of calls to Lookup before a new check for expired sessions. + size_t expiration_check_count = 256; + // How long each session should last. + base::TimeDelta timeout = base::TimeDelta::FromHours(1); + }; + + explicit SSLClientSessionCacheOpenSSL(const Config& config); + ~SSLClientSessionCacheOpenSSL(); + + size_t size() const; + + // Returns the session associated with |cache_key| and moves it to the front + // of the MRU list. Returns null if there is none. The caller is responsible + // for taking a reference to the pointer if the cache is destroyed or a call + // to Insert is made. + SSL_SESSION* Lookup(const std::string& cache_key); + + // Inserts |session| into the cache at |cache_key|. If there is an existing + // one, it is released. Every |expiration_check_count| calls, the cache is + // checked for stale entries. + void Insert(const std::string& cache_key, SSL_SESSION* session); + + // Removes all entries from the cache. + void Flush(); + + void SetClockForTesting(scoped_ptr<base::Clock> clock); + + private: + struct CacheEntry { + CacheEntry(); + ~CacheEntry(); + + ScopedSSL_SESSION session; + // The time at which this entry was created. + base::Time creation_time; + }; + + using CacheEntryMap = + base::MRUCacheBase<std::string, + CacheEntry*, + base::MRUCachePointerDeletor<CacheEntry*>, + base::MRUCacheHashMap>; + + // Returns true if |entry| is expired as of |now|. + bool IsExpired(CacheEntry* entry, const base::Time& now); + + // Removes all expired sessions from the cache. + void FlushExpiredSessions(); + + scoped_ptr<base::Clock> clock_; + Config config_; + CacheEntryMap cache_; + size_t lookups_since_flush_; + + base::ThreadChecker thread_checker_; + + DISALLOW_COPY_AND_ASSIGN(SSLClientSessionCacheOpenSSL); +}; + +} // namespace net + +#endif // NET_SSL_SSL_CLIENT_SESSION_CACHE_OPENSSL_H
diff --git a/net/ssl/ssl_client_session_cache_openssl_unittest.cc b/net/ssl/ssl_client_session_cache_openssl_unittest.cc new file mode 100644 index 0000000..8cb9eab --- /dev/null +++ b/net/ssl/ssl_client_session_cache_openssl_unittest.cc
@@ -0,0 +1,226 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ssl/ssl_client_session_cache_openssl.h" + +#include <openssl/ssl.h> + +#include "base/strings/string_number_conversions.h" +#include "base/test/simple_test_clock.h" +#include "net/ssl/scoped_openssl_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +// Test basic insertion and lookup operations. +TEST(SSLClientSessionCacheOpenSSLTest, Basic) { + SSLClientSessionCacheOpenSSL::Config config; + SSLClientSessionCacheOpenSSL cache(config); + + ScopedSSL_SESSION session1(SSL_SESSION_new()); + ScopedSSL_SESSION session2(SSL_SESSION_new()); + ScopedSSL_SESSION session3(SSL_SESSION_new()); + EXPECT_EQ(1, session1->references); + EXPECT_EQ(1, session2->references); + EXPECT_EQ(1, session3->references); + + EXPECT_EQ(nullptr, cache.Lookup("key1")); + EXPECT_EQ(nullptr, cache.Lookup("key2")); + EXPECT_EQ(0u, cache.size()); + + cache.Insert("key1", session1.get()); + EXPECT_EQ(session1.get(), cache.Lookup("key1")); + EXPECT_EQ(nullptr, cache.Lookup("key2")); + EXPECT_EQ(1u, cache.size()); + + cache.Insert("key2", session2.get()); + EXPECT_EQ(session1.get(), cache.Lookup("key1")); + EXPECT_EQ(session2.get(), cache.Lookup("key2")); + EXPECT_EQ(2u, cache.size()); + + EXPECT_EQ(2, session1->references); + EXPECT_EQ(2, session2->references); + + cache.Insert("key1", session3.get()); + EXPECT_EQ(session3.get(), cache.Lookup("key1")); + EXPECT_EQ(session2.get(), cache.Lookup("key2")); + EXPECT_EQ(2u, cache.size()); + + EXPECT_EQ(1, session1->references); + EXPECT_EQ(2, session2->references); + EXPECT_EQ(2, session3->references); + + cache.Flush(); + EXPECT_EQ(nullptr, cache.Lookup("key1")); + EXPECT_EQ(nullptr, cache.Lookup("key2")); + EXPECT_EQ(nullptr, cache.Lookup("key3")); + EXPECT_EQ(0u, cache.size()); + + EXPECT_EQ(1, session1->references); + EXPECT_EQ(1, session2->references); + EXPECT_EQ(1, session3->references); +} + +// Test that a session may be inserted at two different keys. This should never +// be necessary, but the API doesn't prohibit it. +TEST(SSLClientSessionCacheOpenSSLTest, DoubleInsert) { + SSLClientSessionCacheOpenSSL::Config config; + SSLClientSessionCacheOpenSSL cache(config); + + ScopedSSL_SESSION session(SSL_SESSION_new()); + EXPECT_EQ(1, session->references); + + EXPECT_EQ(nullptr, cache.Lookup("key1")); + EXPECT_EQ(nullptr, cache.Lookup("key2")); + EXPECT_EQ(0u, cache.size()); + + cache.Insert("key1", session.get()); + EXPECT_EQ(session.get(), cache.Lookup("key1")); + EXPECT_EQ(nullptr, cache.Lookup("key2")); + EXPECT_EQ(1u, cache.size()); + + EXPECT_EQ(2, session->references); + + cache.Insert("key2", session.get()); + EXPECT_EQ(session.get(), cache.Lookup("key1")); + EXPECT_EQ(session.get(), cache.Lookup("key2")); + EXPECT_EQ(2u, cache.size()); + + EXPECT_EQ(3, session->references); + + cache.Flush(); + EXPECT_EQ(nullptr, cache.Lookup("key1")); + EXPECT_EQ(nullptr, cache.Lookup("key2")); + EXPECT_EQ(0u, cache.size()); + + EXPECT_EQ(1, session->references); +} + +// Tests that the session cache's size is correctly bounded. +TEST(SSLClientSessionCacheOpenSSLTest, MaxEntries) { + SSLClientSessionCacheOpenSSL::Config config; + config.max_entries = 3; + SSLClientSessionCacheOpenSSL cache(config); + + ScopedSSL_SESSION session1(SSL_SESSION_new()); + ScopedSSL_SESSION session2(SSL_SESSION_new()); + ScopedSSL_SESSION session3(SSL_SESSION_new()); + ScopedSSL_SESSION session4(SSL_SESSION_new()); + + // Insert three entries. + cache.Insert("key1", session1.get()); + cache.Insert("key2", session2.get()); + cache.Insert("key3", session3.get()); + EXPECT_EQ(session1.get(), cache.Lookup("key1")); + EXPECT_EQ(session2.get(), cache.Lookup("key2")); + EXPECT_EQ(session3.get(), cache.Lookup("key3")); + EXPECT_EQ(3u, cache.size()); + + // On insertion of a fourth, the first is removed. + cache.Insert("key4", session4.get()); + EXPECT_EQ(nullptr, cache.Lookup("key1")); + EXPECT_EQ(session4.get(), cache.Lookup("key4")); + EXPECT_EQ(session3.get(), cache.Lookup("key3")); + EXPECT_EQ(session2.get(), cache.Lookup("key2")); + EXPECT_EQ(3u, cache.size()); + + // Despite being newest, the next to be removed is session4 as it was accessed + // least. recently. + cache.Insert("key1", session1.get()); + EXPECT_EQ(session1.get(), cache.Lookup("key1")); + EXPECT_EQ(session2.get(), cache.Lookup("key2")); + EXPECT_EQ(session3.get(), cache.Lookup("key3")); + EXPECT_EQ(nullptr, cache.Lookup("key4")); + EXPECT_EQ(3u, cache.size()); +} + +// Tests that session expiration works properly. +TEST(SSLClientSessionCacheOpenSSLTest, Expiration) { + const size_t kNumEntries = 20; + const size_t kExpirationCheckCount = 10; + const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); + + SSLClientSessionCacheOpenSSL::Config config; + config.expiration_check_count = kExpirationCheckCount; + config.timeout = kTimeout; + SSLClientSessionCacheOpenSSL cache(config); + base::SimpleTestClock* clock = new base::SimpleTestClock; + cache.SetClockForTesting(make_scoped_ptr(clock)); + + // Add |kNumEntries - 1| entries. + for (size_t i = 0; i < kNumEntries - 1; i++) { + ScopedSSL_SESSION session(SSL_SESSION_new()); + cache.Insert(base::SizeTToString(i), session.get()); + } + EXPECT_EQ(kNumEntries - 1, cache.size()); + + // Expire all the previous entries and insert one more entry. + clock->Advance(kTimeout * 2); + ScopedSSL_SESSION session(SSL_SESSION_new()); + cache.Insert("key", session.get()); + + // All entries are still in the cache. + EXPECT_EQ(kNumEntries, cache.size()); + + // Perform one fewer lookup than needed to trigger the expiration check. This + // shall not expire any session. + for (size_t i = 0; i < kExpirationCheckCount - 1; i++) + cache.Lookup("key"); + + // All entries are still in the cache. + EXPECT_EQ(kNumEntries, cache.size()); + + // Perform one more lookup. This will expire all sessions but the last one. + cache.Lookup("key"); + EXPECT_EQ(1u, cache.size()); + EXPECT_EQ(session.get(), cache.Lookup("key")); + for (size_t i = 0; i < kNumEntries - 1; i++) { + SCOPED_TRACE(i); + EXPECT_EQ(nullptr, cache.Lookup(base::SizeTToString(i))); + } +} + +// Tests that Lookup performs an expiration check before returning a cached +// session. +TEST(SSLClientSessionCacheOpenSSLTest, LookupExpirationCheck) { + // kExpirationCheckCount is set to a suitably large number so the automated + // pruning never triggers. + const size_t kExpirationCheckCount = 1000; + const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000); + + SSLClientSessionCacheOpenSSL::Config config; + config.expiration_check_count = kExpirationCheckCount; + config.timeout = kTimeout; + SSLClientSessionCacheOpenSSL cache(config); + base::SimpleTestClock* clock = new base::SimpleTestClock; + cache.SetClockForTesting(make_scoped_ptr(clock)); + + // Insert an entry into the session cache. + ScopedSSL_SESSION session(SSL_SESSION_new()); + cache.Insert("key", session.get()); + EXPECT_EQ(session.get(), cache.Lookup("key")); + EXPECT_EQ(1u, cache.size()); + + // Expire the session. + clock->Advance(kTimeout * 2); + + // The entry has not been removed yet. + EXPECT_EQ(1u, cache.size()); + + // But it will not be returned on lookup and gets pruned at that point. + EXPECT_EQ(nullptr, cache.Lookup("key")); + EXPECT_EQ(0u, cache.size()); + + // Sessions also are treated as expired if the clock rewinds. + cache.Insert("key", session.get()); + EXPECT_EQ(session.get(), cache.Lookup("key")); + EXPECT_EQ(1u, cache.size()); + + clock->Advance(-kTimeout * 2); + + EXPECT_EQ(nullptr, cache.Lookup("key")); + EXPECT_EQ(0u, cache.size()); +} + +} // namespace net
diff --git a/net/test/net_test_suite.cc b/net/test/net_test_suite.cc index ed8a103..ee05b86 100644 --- a/net/test/net_test_suite.cc +++ b/net/test/net_test_suite.cc
@@ -11,7 +11,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if defined(USE_NSS) || defined(OS_IOS) -#include "net/ocsp/nss_ocsp.h" +#include "net/cert_net/nss_ocsp.h" #endif class StaticReset : public ::testing::EmptyTestEventListener {
diff --git a/net/test/spawned_test_server/base_test_server.cc b/net/test/spawned_test_server/base_test_server.cc index f2eea30..3eeb685 100644 --- a/net/test/spawned_test_server/base_test_server.cc +++ b/net/test/spawned_test_server/base_test_server.cc
@@ -29,11 +29,17 @@ std::string GetHostname(BaseTestServer::Type type, const BaseTestServer::SSLOptions& options) { - if (BaseTestServer::UsingSSL(type) && - options.server_certificate == - BaseTestServer::SSLOptions::CERT_MISMATCHED_NAME) { - // Return a different hostname string that resolves to the same hostname. - return "localhost"; + if (BaseTestServer::UsingSSL(type)) { + if (options.server_certificate == + BaseTestServer::SSLOptions::CERT_MISMATCHED_NAME || + options.server_certificate == + BaseTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN) { + // For |CERT_MISMATCHED_NAME|, return a different hostname string + // that resolves to the same hostname. For + // |CERT_COMMON_NAME_IS_DOMAIN|, the certificate is issued for + // "localhost" instead of "127.0.0.1". + return "localhost"; + } } // Use the 127.0.0.1 as default. @@ -135,6 +141,8 @@ case CERT_OK: case CERT_MISMATCHED_NAME: return base::FilePath(FILE_PATH_LITERAL("ok_cert.pem")); + case CERT_COMMON_NAME_IS_DOMAIN: + return base::FilePath(FILE_PATH_LITERAL("localhost_cert.pem")); case CERT_EXPIRED: return base::FilePath(FILE_PATH_LITERAL("expired_cert.pem")); case CERT_CHAIN_WRONG_ROOT:
diff --git a/net/test/spawned_test_server/base_test_server.h b/net/test/spawned_test_server/base_test_server.h index c2d42ee..5fd57f1 100644 --- a/net/test/spawned_test_server/base_test_server.h +++ b/net/test/spawned_test_server/base_test_server.h
@@ -61,6 +61,10 @@ // TestRootStore) is expected to have a self-signed version of the // intermediate. CERT_CHAIN_WRONG_ROOT, + + // Causes the testserver to use a hostname that is a domain + // instead of an IP. + CERT_COMMON_NAME_IS_DOMAIN, }; // OCSPStatus enumerates the types of OCSP response that the testserver
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py index bda4f90..b7bce97 100755 --- a/net/tools/testserver/testserver.py +++ b/net/tools/testserver/testserver.py
@@ -1980,6 +1980,14 @@ port = self.options.port host = self.options.host + # Work around a bug in Mac OS 10.6. Spawning a WebSockets server + # will result in a call to |getaddrinfo|, which fails with "nodename + # nor servname provided" for localhost:0 on 10.6. + if self.options.server_type == SERVER_WEBSOCKET and \ + host == "localhost" and \ + port == 0: + host = "127.0.0.1" + if self.options.server_type == SERVER_HTTP: if self.options.https: pem_cert_and_key = None @@ -2085,6 +2093,8 @@ 'specified trusted client CA file not found: ' + self.options.ssl_client_ca[0] + ' exiting...') websocket_options.tls_client_ca = self.options.ssl_client_ca[0] + print 'Trying to start websocket server on %s://%s:%d...' % \ + (scheme, websocket_options.server_host, websocket_options.port) server = WebSocketServer(websocket_options) print 'WebSocket server started on %s://%s:%d...' % \ (scheme, host, server.server_port)
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc index f08e382..60d6d01a 100644 --- a/net/url_request/url_fetcher_impl_unittest.cc +++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -33,7 +33,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if defined(USE_NSS) || defined(OS_IOS) -#include "net/ocsp/nss_ocsp.h" +#include "net/cert_net/nss_ocsp.h" #endif namespace net {
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 1a60ac4..890620a9 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -794,6 +794,10 @@ !security_state) return; + // Don't accept HSTS headers when the hostname is an IP address. + if (request_info_.url.HostIsIPAddress()) + return; + // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec: // // If a UA receives more than one STS header field in a HTTP response @@ -817,6 +821,10 @@ !security_state) return; + // Don't accept HSTS headers when the hostname is an IP address. + if (request_info_.url.HostIsIPAddress()) + return; + // http://tools.ietf.org/html/draft-ietf-websec-key-pinning: // // If a UA receives more than one PKP header field in an HTTP
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 52b63a1..e86672c6 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -45,6 +45,7 @@ #include "net/cert/ev_root_ca_metadata.h" #include "net/cert/mock_cert_verifier.h" #include "net/cert/test_root_certs.h" +#include "net/cert_net/nss_ocsp.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store_test_helpers.h" #include "net/disk_cache/disk_cache.h" @@ -60,7 +61,6 @@ #include "net/log/capturing_net_log.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" -#include "net/ocsp/nss_ocsp.h" #include "net/proxy/proxy_service.h" #include "net/socket/ssl_client_socket.h" #include "net/ssl/ssl_cipher_suite_names.h" @@ -5258,13 +5258,16 @@ } TEST_F(URLRequestTestHTTP, ProcessSTS) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_test_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); ASSERT_TRUE(https_test_server.Start()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( https_test_server.GetURL("files/hsts-headers.html"), DEFAULT_PRIORITY, @@ -5275,8 +5278,8 @@ TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(security_state->GetDynamicDomainState( - SpawnedTestServer::kLocalhost, &domain_state)); + EXPECT_TRUE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); EXPECT_EQ(TransportSecurityState::DomainState::MODE_FORCE_HTTPS, domain_state.sts.upgrade_mode); EXPECT_TRUE(domain_state.sts.include_subdomains); @@ -5288,6 +5291,30 @@ #endif } +TEST_F(URLRequestTestHTTP, STSNotProcessedOnIP) { + SpawnedTestServer https_test_server( + SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::SSLOptions(), + base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); + ASSERT_TRUE(https_test_server.Start()); + // Make sure this test fails if the test server is changed to not + // listen on an IP by default. + ASSERT_TRUE(https_test_server.GetURL("").HostIsIPAddress()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + + TestDelegate d; + scoped_ptr<URLRequest> request(default_context_.CreateRequest( + https_test_server.GetURL("files/hsts-headers.html"), DEFAULT_PRIORITY, + &d)); + request->Start(); + base::RunLoop().Run(); + + TransportSecurityState* security_state = + default_context_.transport_security_state(); + TransportSecurityState::DomainState domain_state; + EXPECT_FALSE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); +} + // Android's CertVerifyProc does not (yet) handle pins. Therefore, it will // reject HPKP headers, and a test setting only HPKP headers will fail (no // DomainState present because header rejected). @@ -5300,13 +5327,16 @@ // Tests that enabling HPKP on a domain does not affect the HSTS // validity/expiration. TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKP) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_test_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); ASSERT_TRUE(https_test_server.Start()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( https_test_server.GetURL("files/hpkp-headers.html"), DEFAULT_PRIORITY, @@ -5317,8 +5347,8 @@ TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(security_state->GetDynamicDomainState( - SpawnedTestServer::kLocalhost, &domain_state)); + EXPECT_TRUE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); EXPECT_EQ(TransportSecurityState::DomainState::MODE_DEFAULT, domain_state.sts.upgrade_mode); EXPECT_FALSE(domain_state.sts.include_subdomains); @@ -5327,14 +5357,41 @@ EXPECT_NE(domain_state.sts.expiry, domain_state.pkp.expiry); } +TEST_F(URLRequestTestHTTP, PKPNotProcessedOnIP) { + SpawnedTestServer https_test_server( + SpawnedTestServer::TYPE_HTTPS, SpawnedTestServer::SSLOptions(), + base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); + ASSERT_TRUE(https_test_server.Start()); + // Make sure this test fails if the test server is changed to not + // listen on an IP by default. + ASSERT_TRUE(https_test_server.GetURL("").HostIsIPAddress()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + + TestDelegate d; + scoped_ptr<URLRequest> request(default_context_.CreateRequest( + https_test_server.GetURL("files/hpkp-headers.html"), DEFAULT_PRIORITY, + &d)); + request->Start(); + base::RunLoop().Run(); + + TransportSecurityState* security_state = + default_context_.transport_security_state(); + TransportSecurityState::DomainState domain_state; + EXPECT_FALSE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); +} + TEST_F(URLRequestTestHTTP, ProcessSTSOnce) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_test_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); ASSERT_TRUE(https_test_server.Start()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( https_test_server.GetURL("files/hsts-multiple-headers.html"), @@ -5346,8 +5403,8 @@ TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(security_state->GetDynamicDomainState( - SpawnedTestServer::kLocalhost, &domain_state)); + EXPECT_TRUE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); EXPECT_EQ(TransportSecurityState::DomainState::MODE_FORCE_HTTPS, domain_state.sts.upgrade_mode); EXPECT_FALSE(domain_state.sts.include_subdomains); @@ -5355,13 +5412,16 @@ } TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_test_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); ASSERT_TRUE(https_test_server.Start()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( https_test_server.GetURL("files/hsts-and-hpkp-headers.html"), @@ -5373,8 +5433,8 @@ TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(security_state->GetDynamicDomainState( - SpawnedTestServer::kLocalhost, &domain_state)); + EXPECT_TRUE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); EXPECT_EQ(TransportSecurityState::DomainState::MODE_FORCE_HTTPS, domain_state.sts.upgrade_mode); #if defined(OS_ANDROID) @@ -5394,13 +5454,16 @@ // Tests that when multiple HPKP headers are present, asserting different // policies, that only the first such policy is processed. TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP2) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_test_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); ASSERT_TRUE(https_test_server.Start()); + std::string test_server_hostname = https_test_server.GetURL("").host(); + TestDelegate d; scoped_ptr<URLRequest> request(default_context_.CreateRequest( https_test_server.GetURL("files/hsts-and-hpkp-headers2.html"), @@ -5411,8 +5474,8 @@ TransportSecurityState* security_state = default_context_.transport_security_state(); TransportSecurityState::DomainState domain_state; - EXPECT_TRUE(security_state->GetDynamicDomainState( - SpawnedTestServer::kLocalhost, &domain_state)); + EXPECT_TRUE(security_state->GetDynamicDomainState(test_server_hostname, + &domain_state)); EXPECT_EQ(TransportSecurityState::DomainState::MODE_FORCE_HTTPS, domain_state.sts.upgrade_mode); #if defined(OS_ANDROID)
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc index e675d8b3..9dc6c54 100644 --- a/net/websockets/websocket_end_to_end_test.cc +++ b/net/websockets/websocket_end_to_end_test.cc
@@ -385,12 +385,14 @@ // Regression test for crbug.com/455215 "HSTS not applied to WebSocket" TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HstsHttpsToWebSocket)) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options, GetWebSocketTestDataDirectory()); + ASSERT_TRUE(https_server.StartInBackground()); ASSERT_TRUE(wss_server.StartInBackground()); ASSERT_TRUE(https_server.BlockUntilStarted()); @@ -413,7 +415,8 @@ } TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HstsWebSocketToHttps)) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer https_server( SpawnedTestServer::TYPE_HTTPS, ssl_options, base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); @@ -442,7 +445,8 @@ } TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HstsWebSocketToWebSocket)) { - SpawnedTestServer::SSLOptions ssl_options; + SpawnedTestServer::SSLOptions ssl_options( + SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN); SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options, GetWebSocketTestDataDirectory()); ASSERT_TRUE(wss_server.Start());
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc index cf8a5ee..f96d6c08 100644 --- a/printing/pdf_metafile_skia.cc +++ b/printing/pdf_metafile_skia.cc
@@ -121,7 +121,7 @@ return false; DCHECK(!(data_->pages_.back().content_)); data_->pages_.back().content_ = - skia::AdoptRef(data_->recorder_.endRecording()); + skia::AdoptRef(data_->recorder_.endRecordingAsPicture()); return true; }
diff --git a/remoting/host/daemon_process.cc b/remoting/host/daemon_process.cc index c3c7fd9..8c9ebbb2 100644 --- a/remoting/host/daemon_process.cc +++ b/remoting/host/daemon_process.cc
@@ -21,6 +21,7 @@ #include "remoting/host/config_file_watcher.h" #include "remoting/host/desktop_session.h" #include "remoting/host/host_event_logger.h" +#include "remoting/host/host_exit_codes.h" #include "remoting/host/host_status_observer.h" #include "remoting/host/screen_resolution.h" #include "remoting/protocol/transport.h" @@ -132,6 +133,9 @@ void DaemonProcess::OnPermanentError(int exit_code) { DCHECK(caller_task_runner()->BelongsToCurrentThread()); + DCHECK(kMinPermanentErrorExitCode <= exit_code && + exit_code <= kMaxPermanentErrorExitCode); + Stop(); }
diff --git a/remoting/host/daemon_process_win.cc b/remoting/host/daemon_process_win.cc index 85706d5..32bf73a 100644 --- a/remoting/host/daemon_process_win.cc +++ b/remoting/host/daemon_process_win.cc
@@ -140,11 +140,17 @@ } void DaemonProcessWin::OnPermanentError(int exit_code) { - // Change the service start type to 'manual' if the host has been deleted - // remotely. This way the host will not be started every time the machine - // boots until the user re-enable it again. - if (exit_code == kInvalidHostIdExitCode) + DCHECK(kMinPermanentErrorExitCode <= exit_code && + exit_code <= kMaxPermanentErrorExitCode); + + // Both kInvalidHostIdExitCode and kInvalidOauthCredentialsExitCode are + // errors then will never go away with the current config. + // Disabling automatic service start until the host is re-enabled and config + // updated. + if (exit_code == kInvalidHostIdExitCode || + exit_code == kInvalidOauthCredentialsExitCode) { DisableAutoStart(); + } DaemonProcess::OnPermanentError(exit_code); }
diff --git a/remoting/host/installer/win/chromoting.wxs b/remoting/host/installer/win/chromoting.wxs index be2d6f8..274b5a9 100644 --- a/remoting/host/installer/win/chromoting.wxs +++ b/remoting/host/installer/win/chromoting.wxs
@@ -564,7 +564,10 @@ Script="jscript"> <![CDATA[ var ADS_SERVICE_STOPPED = 0x00000001; + var ADS_SERVICE_AUTO_START = 2; var service = GetObject("WinNT://./$(var.ServiceName),Service"); + service.StartType = ADS_SERVICE_AUTO_START; + service.SetInfo(); if (service.Status == ADS_SERVICE_STOPPED) { service.Start(); }
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 96fe46e..2155b88 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -1545,13 +1545,6 @@ scoped_ptr<net::NetworkChangeNotifier> network_change_notifier( net::NetworkChangeNotifier::Create()); - // BasicURLRequestContext holds references to threads, so it needs to be - // dereferences on UI threads. Store the reference to the URLRequestGetter to - // make sure it's not destroyed on other threads. - // TODO(sergeyu): Consider fixing it in BasicURLRequestContext. - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = - context->url_request_context_getter(); - // Create & start the HostProcess using these threads. // TODO(wez): The HostProcess holds a reference to itself until Shutdown(). // Remove this hack as part of the multi-process refactoring.
diff --git a/remoting/remoting_webapp_files.gypi b/remoting/remoting_webapp_files.gypi index aa8e8a8..bb5444c 100644 --- a/remoting/remoting_webapp_files.gypi +++ b/remoting/remoting_webapp_files.gypi
@@ -168,8 +168,8 @@ 'webapp/base/js/app_capabilities.js', 'webapp/base/js/application.js', 'webapp/base/js/base.js', - 'webapp/base/js/input_dialog.js', 'webapp/base/js/ipc.js', + 'webapp/base/js/modal_dialogs.js', 'webapp/base/js/platform.js', 'webapp/base/js/protocol_extension_manager.js', 'webapp/base/js/protocol_extension.js',
diff --git a/remoting/webapp/base/js/application.js b/remoting/webapp/base/js/application.js index 4881380d..4679ab8 100644 --- a/remoting/webapp/base/js/application.js +++ b/remoting/webapp/base/js/application.js
@@ -159,7 +159,6 @@ this.onSessionFinished_.bind(this)), new base.RepeatingTimer(this.updateStatistics_.bind(this), 1000) ); - remoting.clipboard.startSession(); }; /**
diff --git a/remoting/webapp/base/js/input_dialog.js b/remoting/webapp/base/js/input_dialog.js deleted file mode 100644 index a55e016..0000000 --- a/remoting/webapp/base/js/input_dialog.js +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** @suppress {duplicate} */ -var remoting = remoting || {}; - -(function() { - -'use strict'; - -/** - * A helper class for implementing dialogs with an input field using - * remoting.setMode(). - * - * @param {remoting.AppMode} mode - * @param {HTMLElement} formElement - * @param {HTMLElement} inputField - * @param {HTMLElement} cancelButton - * - * @constructor - */ -remoting.InputDialog = function(mode, formElement, inputField, cancelButton) { - /** @private */ - this.appMode_ = mode; - /** @private */ - this.formElement_ = formElement; - /** @private */ - this.cancelButton_ = cancelButton; - /** @private */ - this.inputField_ = inputField; - /** @private {base.Deferred} */ - this.deferred_ = null; - /** @private {base.Disposables} */ - this.eventHooks_ = null; -}; - -/** - * @return {Promise<string>} Promise that resolves with the value of the - * inputField or rejects with |remoting.Error.CANCELLED| if the user clicks - * on the cancel button. - */ -remoting.InputDialog.prototype.show = function() { - var onCancel = this.createFormEventHandler_(this.onCancel_.bind(this)); - var onOk = this.createFormEventHandler_(this.onSubmit_.bind(this)); - - this.eventHooks_ = new base.Disposables( - new base.DomEventHook(this.formElement_, 'submit', onOk, false), - new base.DomEventHook(this.cancelButton_, 'click', onCancel, false)); - base.debug.assert(this.deferred_ === null); - this.deferred_ = new base.Deferred(); - remoting.setMode(this.appMode_); - return this.deferred_.promise(); -}; - -/** @return {HTMLElement} */ -remoting.InputDialog.prototype.inputField = function() { - return this.inputField_; -} - -/** @private */ -remoting.InputDialog.prototype.onSubmit_ = function() { - this.deferred_.resolve(this.inputField_.value); -} - -/** @private */ -remoting.InputDialog.prototype.onCancel_ = function() { - this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); -} - -/** - * @param {function():void} handler - * @return {Function} - * @private - */ -remoting.InputDialog.prototype.createFormEventHandler_ = function(handler) { - var that = this; - return function (/** Event */ e) { - // Prevents form submission from reloading the v1 app. - e.preventDefault(); - - // Set the focus away from the password field. This has to be done - // before the password field gets hidden, to work around a Blink - // clipboard-handling bug - http://crbug.com/281523. - that.cancelButton_.focus(); - handler(); - base.dispose(that.eventHooks_); - that.eventHooks_ = null; - that.deferred_ = null; - }; -}; - -})(); \ No newline at end of file
diff --git a/remoting/webapp/base/js/modal_dialogs.js b/remoting/webapp/base/js/modal_dialogs.js new file mode 100644 index 0000000..0aa3416 --- /dev/null +++ b/remoting/webapp/base/js/modal_dialogs.js
@@ -0,0 +1,160 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @suppress {duplicate} */ +var remoting = remoting || {}; + +(function() { + +'use strict'; + +/** + * A helper class for implementing dialogs with an input field using + * remoting.setMode(). + * + * @param {remoting.AppMode} mode + * @param {HTMLElement} formElement + * @param {HTMLElement} inputField + * @param {HTMLElement} cancelButton + * + * @constructor + */ +remoting.InputDialog = function(mode, formElement, inputField, cancelButton) { + /** @private */ + this.appMode_ = mode; + /** @private */ + this.formElement_ = formElement; + /** @private */ + this.cancelButton_ = cancelButton; + /** @private */ + this.inputField_ = inputField; + /** @private {base.Deferred} */ + this.deferred_ = null; + /** @private {base.Disposables} */ + this.eventHooks_ = null; +}; + +/** + * @return {Promise<string>} Promise that resolves with the value of the + * inputField or rejects with |remoting.Error.CANCELLED| if the user clicks + * on the cancel button. + */ +remoting.InputDialog.prototype.show = function() { + var onCancel = this.createFormEventHandler_(this.onCancel_.bind(this)); + var onOk = this.createFormEventHandler_(this.onSubmit_.bind(this)); + + this.eventHooks_ = new base.Disposables( + new base.DomEventHook(this.formElement_, 'submit', onOk, false), + new base.DomEventHook(this.cancelButton_, 'click', onCancel, false)); + base.debug.assert(this.deferred_ === null); + this.deferred_ = new base.Deferred(); + remoting.setMode(this.appMode_); + return this.deferred_.promise(); +}; + +/** @return {HTMLElement} */ +remoting.InputDialog.prototype.inputField = function() { + return this.inputField_; +} + +/** @private */ +remoting.InputDialog.prototype.onSubmit_ = function() { + this.deferred_.resolve(this.inputField_.value); +} + +/** @private */ +remoting.InputDialog.prototype.onCancel_ = function() { + this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); +} + +/** + * @param {function():void} handler + * @return {Function} + * @private + */ +remoting.InputDialog.prototype.createFormEventHandler_ = function(handler) { + var that = this; + return function (/** Event */ e) { + // Prevents form submission from reloading the v1 app. + e.preventDefault(); + + // Set the focus away from the password field. This has to be done + // before the password field gets hidden, to work around a Blink + // clipboard-handling bug - http://crbug.com/281523. + that.cancelButton_.focus(); + handler(); + base.dispose(that.eventHooks_); + that.eventHooks_ = null; + that.deferred_ = null; + }; +}; + +/** + * A helper class for implementing MessageDialog with a primary and + * and secondary button using remoting.setMode(). + * + * @param {remoting.AppMode} mode + * @param {HTMLElement} primaryButton + * @param {HTMLElement=} opt_secondaryButton + * @constructor + */ +remoting.MessageDialog = function(mode, primaryButton, opt_secondaryButton) { + /** @private @const */ + this.mode_ = mode; + /** @private @const */ + this.primaryButton_ = primaryButton; + /** @private @const */ + this.secondaryButton_ = opt_secondaryButton; + /** @private {base.Deferred} */ + this.deferred_ = null; + /** @private {base.Disposables} */ + this.eventHooks_ = null; +}; + +/** + * @return {Promise<remoting.MessageDialog.Result>} Promise that resolves with + * the button clicked. + */ +remoting.MessageDialog.prototype.show = function() { + this.eventHooks_ = new base.Disposables(new base.DomEventHook( + this.primaryButton_, 'click', + this.onClicked_.bind(this, remoting.MessageDialog.Result.PRIMARY), + false)); + + if (this.secondaryButton_) { + this.eventHooks_.add(new base.DomEventHook( + this.secondaryButton_, 'click', + this.onClicked_.bind(this, remoting.MessageDialog.Result.SECONDARY), + false)); + } + + base.debug.assert(this.deferred_ === null); + this.deferred_ = new base.Deferred(); + remoting.setMode(this.mode_); + return this.deferred_.promise(); +}; + +/** + * @param {remoting.MessageDialog.Result} result + * @return {Function} + * @private + */ +remoting.MessageDialog.prototype.onClicked_ = function(result) { + this.deferred_.resolve(result); + base.dispose(this.eventHooks_); + this.eventHooks_ = null; + this.deferred_ = null; +}; + +})(); + +/** + * Define the enum at the end of file as JSCompile doesn't understand enums that + * are defined within an IIFE (Immediately Invoked Function Expression). + * @enum {number} + */ +remoting.MessageDialog.Result = { + PRIMARY: 0, + SECONDARY: 1 +}; \ No newline at end of file
diff --git a/remoting/webapp/build-webapp.py b/remoting/webapp/build-webapp.py index fb10150c1..979b593 100755 --- a/remoting/webapp/build-webapp.py +++ b/remoting/webapp/build-webapp.py
@@ -355,7 +355,7 @@ if not app_client_id: raise Exception('Invalid app_client_id passed in: "' + app_client_id + '"') - apiClientIdV2 = app_client_id + apiClientIdV2 = app_client_id + '.apps.googleusercontent.com' else: apiClientIdV2 = google_api_keys.GetClientID('REMOTING_IDENTITY_API')
diff --git a/remoting/webapp/crd/js/client_plugin.js b/remoting/webapp/crd/js/client_plugin.js index e8b3f8d..31bb60e7 100644 --- a/remoting/webapp/crd/js/client_plugin.js +++ b/remoting/webapp/crd/js/client_plugin.js
@@ -157,8 +157,14 @@ * URL encoding the mouse cursor; the second and third parameters are * the cursor hotspot's x- and y-coordinates, respectively. */ -remoting.ClientPlugin.prototype.setMouseCursorHandler = - function(handler) {}; +remoting.ClientPlugin.prototype.setMouseCursorHandler = function(handler) {}; + +/** + * @param {function(string, string):void} handler Callback for processing + * clipboard data injected from the host. The first parameter is the mime + * type and the second parameter is the actual data. + */ +remoting.ClientPlugin.prototype.setClipboardHandler = function(handler) {}; /** * @param {function({rects:Array<Array<number>>}):void|null} handler Callback
diff --git a/remoting/webapp/crd/js/client_plugin_impl.js b/remoting/webapp/crd/js/client_plugin_impl.js index c3808b4..0e0f916f 100644 --- a/remoting/webapp/crd/js/client_plugin_impl.js +++ b/remoting/webapp/crd/js/client_plugin_impl.js
@@ -44,23 +44,12 @@ /** @private {remoting.ClientPlugin.ConnectionEventHandler} */ this.connectionEventHandler_ = null; - /** - * @param {string} data Remote gnubbyd data. - * @private - */ - this.onGnubbyAuthHandler_ = function(data) {}; - /** - * @param {string} url - * @param {number} hotspotX - * @param {number} hotspotY - * @private - */ - this.updateMouseCursorImage_ = function(url, hotspotX, hotspotY) {}; - /** - * @param {string} data Remote cast extension message. - * @private - */ - this.onCastExtensionHandler_ = function(data) {}; + /** @private {?function(string, number, number)} */ + this.updateMouseCursorImage_ = base.doNothing; + /** @private {?function(string, string)} */ + this.updateClipboardData_ = base.doNothing; + /** @private {?function(string)} */ + this.onCastExtensionHandler_ = base.doNothing; /** @private {?function({rects:Array<Array<number>>}):void} */ this.debugRegionHandler_ = null; @@ -168,6 +157,13 @@ }; /** + * @param {function(string, string):void} handler + */ +remoting.ClientPluginImpl.prototype.setClipboardHandler = function(handler) { + this.updateClipboardData_ = handler; +}; + +/** * @param {?function({rects:Array<Array<number>>}):void} handler */ remoting.ClientPluginImpl.prototype.setDebugDirtyRegionHandler = @@ -310,9 +306,7 @@ } else if (message.method == 'injectClipboardItem') { var mimetype = base.getStringAttr(message.data, 'mimeType'); var item = base.getStringAttr(message.data, 'item'); - if (remoting.clipboard) { - remoting.clipboard.fromHost(mimetype, item); - } + this.updateClipboardData_(mimetype, item); } else if (message.method == 'onFirstFrameReceived') { if (remoting.clientSession) {
diff --git a/remoting/webapp/crd/js/client_session.js b/remoting/webapp/crd/js/client_session.js index 0328535..05a8a990 100644 --- a/remoting/webapp/crd/js/client_session.js +++ b/remoting/webapp/crd/js/client_session.js
@@ -567,18 +567,6 @@ }; /** - * Sends a clipboard item to the host. - * - * @param {string} mimeType The MIME type of the clipboard item. - * @param {string} item The clipboard item. - */ -remoting.ClientSession.prototype.sendClipboardItem = function(mimeType, item) { - if (!this.plugin_) - return; - this.plugin_.sendClipboardItem(mimeType, item); -}; - -/** * Sends an extension message to the host. * * @param {string} type The message type.
diff --git a/remoting/webapp/crd/js/clipboard.js b/remoting/webapp/crd/js/clipboard.js index 0d116779..9d2b48c 100644 --- a/remoting/webapp/crd/js/clipboard.js +++ b/remoting/webapp/crd/js/clipboard.js
@@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,52 +7,60 @@ * A class for moving clipboard items between the plugin and the OS. */ -'use strict'; - /** @suppress {duplicate} */ var remoting = remoting || {}; -/** - * @constructor - */ -remoting.Clipboard = function() { -}; +(function() { + +'use strict'; /** * @private * @enum {string} */ -remoting.Clipboard.prototype.ItemTypes = { +var ItemTypes = { TEXT_TYPE: 'text/plain', TEXT_UTF8_TYPE: 'text/plain; charset=UTF-8' }; -/** @private {string} */ -remoting.Clipboard.prototype.previousContent = ""; - -/** @private {boolean} */ -remoting.Clipboard.prototype.itemFromHostTextPending = false; - -/** @private {boolean} */ -remoting.Clipboard.prototype.blockOneClipboardSend_ = false; - /** - * Notifies this object that a session has started. - * - * @return {void} Nothing. + * @constructor + * @param {remoting.ClientPlugin} plugin + * @implements {base.Disposable} */ -remoting.Clipboard.prototype.startSession = function() { - // Clear the store of items sent and received. Those items now relate to a - // previous session. - this.previousContent = ""; - this.itemFromHostTextPending = false; +remoting.Clipboard = function(plugin) { + /** @private {string} */ + this.previousContent_ = ''; + + /** @private {boolean} */ + this.itemFromHostTextPending_ = false; + + /** @private {boolean} */ + this.blockOneClipboardSend_ = true; + + /** @private */ + this.plugin_ = plugin; + + /** @private */ + this.eventHooks_ = new base.Disposables( + new base.DomEventHook(plugin.element(), 'focus', + this.initiateToHost_.bind(this), false), + new base.DomEventHook(window, 'paste', this.onPaste_.bind(this), false), + new base.DomEventHook(window, 'copy', this.onCopy_.bind(this), false)); // Do a paste operation, but make sure the resulting clipboard data isn't sent // to the host. This stops the host seeing items that were placed on the // clipboard before the session began. The user may not have intended such // items to be sent to the host. - this.blockOneClipboardSend_ = true; - this.initiateToHost(); + this.initiateToHost_(); + this.plugin_.setClipboardHandler(this.fromHost_.bind(this)); +}; + +remoting.Clipboard.prototype.dispose = function() { + this.plugin_.setClipboardHandler(base.doNothing); + this.plugin_ = null; + base.dispose(this.eventHooks_); + this.eventHooks_ = null; }; /** @@ -63,37 +71,34 @@ * * @param {ClipboardData} clipboardData * @return {void} Nothing. + * @private */ -remoting.Clipboard.prototype.toHost = function(clipboardData) { +remoting.Clipboard.prototype.toHost_ = function(clipboardData) { if (!clipboardData || !clipboardData.types || !clipboardData.getData) { console.log('Got invalid clipboardData.'); return; } - if (!remoting.clientSession) { - return; - } for (var i = 0; i < clipboardData.types.length; i++) { var type = clipboardData.types[i]; var item = clipboardData.getData(type); if (!item) { - item = ""; + item = ''; } console.log('Got clipboard from OS, type: ' + type + ' length: ' + item.length + ' new: ' + - (item != this.previousContent) + ' blocking-send: ' + + (item != this.previousContent_) + ' blocking-send: ' + this.blockOneClipboardSend_); // The browser presents text clipboard items as 'text/plain'. - if (type == this.ItemTypes.TEXT_TYPE) { + if (type == ItemTypes.TEXT_TYPE) { // Don't send the same item more than once. Otherwise the item may be // sent to and fro indefinitely. - if (item != this.previousContent) { + if (item != this.previousContent_) { if (!this.blockOneClipboardSend_) { // The plugin's JSON reader emits UTF-8. console.log('Sending clipboard to host.'); - remoting.clientSession.sendClipboardItem( - this.ItemTypes.TEXT_UTF8_TYPE, item); + this.plugin_.sendClipboardItem(ItemTypes.TEXT_UTF8_TYPE, item); } - this.previousContent = item; + this.previousContent_ = item; } } } @@ -108,21 +113,21 @@ * @param {string} item The clipboard item. * @return {void} Nothing. */ -remoting.Clipboard.prototype.fromHost = function(mimeType, item) { +remoting.Clipboard.prototype.fromHost_ = function(mimeType, item) { // The plugin's JSON layer will correctly convert only UTF-8 data sent from // the host. console.log('Got clipboard from host, type: ' + mimeType + ' length: ' + item.length + ' new: ' + - (item != this.previousContent)); - if (mimeType != this.ItemTypes.TEXT_UTF8_TYPE) { + (item != this.previousContent_)); + if (mimeType != ItemTypes.TEXT_UTF8_TYPE) { return; } - if (item == this.previousContent) { + if (item == this.previousContent_) { return; } - this.previousContent = item; - this.itemFromHostTextPending = true; - this.initiateToOs(); + this.previousContent_ = item; + this.itemFromHostTextPending_ = true; + this.initiateToOs_(); }; /** @@ -131,9 +136,10 @@ * @param {ClipboardData} clipboardData * @return {boolean} Whether any clipboard items were moved to the ClipboardData * object. + * @private */ -remoting.Clipboard.prototype.toOs = function(clipboardData) { - if (!this.itemFromHostTextPending) { +remoting.Clipboard.prototype.toOs_ = function(clipboardData) { + if (!this.itemFromHostTextPending_) { console.log('Got unexpected clipboard copy event.'); return false; } @@ -141,9 +147,9 @@ // JS string encoding. The browser will convert JS strings to the correct // encoding, per OS and locale conventions, provided the data type is // 'text/plain'. - console.log('Setting OS clipboard, length: ' + this.previousContent.length); - clipboardData.setData(this.ItemTypes.TEXT_TYPE, this.previousContent); - this.itemFromHostTextPending = false; + console.log('Setting OS clipboard, length: ' + this.previousContent_.length); + clipboardData.setData(ItemTypes.TEXT_TYPE, this.previousContent_); + this.itemFromHostTextPending_ = false; return true; }; @@ -154,12 +160,13 @@ * This method makes the browser fire a paste event, which provides access to * the OS clipboard. That event will be caught by a handler in the document, * which will call toHost(). + * @private */ -remoting.Clipboard.prototype.initiateToHost = function() { +remoting.Clipboard.prototype.initiateToHost_ = function() { // It would be cleaner to send a paste command to the plugin element, // but that's not supported. //console.log('Initiating clipboard paste.'); - document.execCommand("paste"); + document.execCommand('paste'); }; /** @@ -169,13 +176,40 @@ * This method makes the browser fire a copy event, which provides access to * the OS clipboard. That event will be caught by a handler in the document, * which will call toOs(). + * @private */ -remoting.Clipboard.prototype.initiateToOs = function() { +remoting.Clipboard.prototype.initiateToOs_ = function() { // It would be cleaner to send a paste command to the plugin element, // but that's not supported. console.log('Initiating clipboard copy.'); - document.execCommand("copy"); + document.execCommand('copy'); }; -/** @type {remoting.Clipboard} */ -remoting.clipboard = null; +/** + * Callback function called when the browser window gets a paste operation. + * + * @param {Event} event + * @return {void} Nothing. + * @private + */ +remoting.Clipboard.prototype.onPaste_ = function(event) { + if (event && event.clipboardData) { + this.toHost_(event.clipboardData); + } +}; + +/** + * Callback function called when the browser window gets a copy operation. + * + * @param {Event} event + * @return {void} Nothing. + * @private + */ +remoting.Clipboard.prototype.onCopy_ = function(event) { + if (event && event.clipboardData && this.toOs_(event.clipboardData)) { + // The default action may overwrite items that we added to clipboardData. + event.preventDefault(); + } +}; + +})();
diff --git a/remoting/webapp/crd/js/connected_view.js b/remoting/webapp/crd/js/connected_view.js index 73f300c..f92656c 100644 --- a/remoting/webapp/crd/js/connected_view.js +++ b/remoting/webapp/crd/js/connected_view.js
@@ -42,12 +42,11 @@ /** private */ this.disposables_ = new base.Disposables( this.cursor_, - new base.DomEventHook(pluginElement, 'focus', - this.onPluginGotFocus_.bind(this), false), new base.DomEventHook(pluginElement, 'blur', this.onPluginLostFocus_.bind(this), false), new base.DomEventHook(document, 'visibilitychange', - this.onVisibilityChanged_.bind(this), false) + this.onVisibilityChanged_.bind(this), false), + new remoting.Clipboard(plugin) ); // TODO(wez): Only allow mouse lock if the app has the pointerLock permission. @@ -91,14 +90,6 @@ }; /** - * Callback function called when the plugin element gets focus. - * @private - */ -remoting.ConnectedView.prototype.onPluginGotFocus_ = function() { - remoting.clipboard.initiateToHost(); -}; - -/** * Callback function called when the plugin element loses focus. * @private */
diff --git a/remoting/webapp/crd/js/crd_event_handlers.js b/remoting/webapp/crd/js/crd_event_handlers.js index 91ee271..01439fa 100644 --- a/remoting/webapp/crd/js/crd_event_handlers.js +++ b/remoting/webapp/crd/js/crd_event_handlers.js
@@ -18,14 +18,9 @@ goHome(); } }; - var reconnect = function() { - remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); - remoting.app.getSessionConnector().reconnect(); - }; /** @type {Array<{event: string, id: string, fn: function(Event):void}>} */ var it2me_actions = [ { event: 'click', id: 'cancel-share-button', fn: remoting.cancelShare }, - { event: 'click', id: 'client-finished-it2me-button', fn: goHome }, { event: 'click', id: 'get-started-it2me', fn: remoting.showIT2MeUiAndSave }, { event: 'click', id: 'host-finished-button', fn: goHome }, @@ -33,8 +28,6 @@ ]; /** @type {Array<{event: string, id: string, fn: function(Event):void}>} */ var me2me_actions = [ - { event: 'click', id: 'client-finished-me2me-button', fn: goHome }, - { event: 'click', id: 'client-reconnect-button', fn: reconnect }, { event: 'click', id: 'daemon-pin-cancel', fn: goHome }, { event: 'click', id: 'get-started-me2me', fn: remoting.showMe2MeUiAndSave }
diff --git a/remoting/webapp/crd/js/it2me_activity.js b/remoting/webapp/crd/js/it2me_activity.js index 144253d..e6eac18 100644 --- a/remoting/webapp/crd/js/it2me_activity.js +++ b/remoting/webapp/crd/js/it2me_activity.js
@@ -81,7 +81,7 @@ }; remoting.It2MeActivity.prototype.onDisconnected = function() { - remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME); + this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME); }; /** @@ -90,9 +90,21 @@ remoting.It2MeActivity.prototype.onError = function(error) { var errorDiv = document.getElementById('connect-error-message'); l10n.localizeElementFromTag(errorDiv, error.getTag()); - remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); + this.showFinishDialog_(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); }; +/** + * @param {remoting.AppMode} mode + * @private + */ +remoting.It2MeActivity.prototype.showFinishDialog_ = function(mode) { + var finishDialog = new remoting.MessageDialog( + mode, + document.getElementById('client-finished-it2me-button')); + finishDialog.show().then(function() { + remoting.setMode(remoting.AppMode.HOME); + }); +}; /** * @param {string} accessCode
diff --git a/remoting/webapp/crd/js/me2me_activity.js b/remoting/webapp/crd/js/me2me_activity.js index 9904e93e..11f156e 100644 --- a/remoting/webapp/crd/js/me2me_activity.js +++ b/remoting/webapp/crd/js/me2me_activity.js
@@ -27,6 +27,7 @@ /** @private */ this.hostUpdateDialog_ = new remoting.HostNeedsUpdateDialog( document.getElementById('host-needs-update-dialog'), this.host_); + /** @private */ this.retryOnHostOffline_ = true; }; @@ -130,17 +131,40 @@ }; remoting.Me2MeActivity.prototype.onDisconnected = function() { - remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME); + this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME); }; /** * @param {!remoting.Error} error */ remoting.Me2MeActivity.prototype.onError = function(error) { - this.retryOnHostOffline_ = true; var errorDiv = document.getElementById('connect-error-message'); l10n.localizeElementFromTag(errorDiv, error.getTag()); - remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME); + this.showFinishDialog_(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME); +}; + +/** + * @param {remoting.AppMode} mode + * @private + */ +remoting.Me2MeActivity.prototype.showFinishDialog_ = function(mode) { + var dialog = new remoting.MessageDialog( + mode, + document.getElementById('client-finished-me2me-button'), + document.getElementById('client-reconnect-button')); + + /** @typedef {remoting.MessageDialog.Result} */ + var Result = remoting.MessageDialog.Result; + var that = this; + + dialog.show().then(function(/** Result */result) { + if (result === Result.PRIMARY) { + remoting.setMode(remoting.AppMode.HOME); + } else { + that.connector_.reconnect(); + remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); + } + }); }; /** @@ -152,11 +176,10 @@ /** @private */ this.host_ = host; /** @private */ - this.rootElement_ = rootElement; - /** @private {base.Deferred} */ - this.deferred_ = null; - /** @private {base.Disposables} */ - this.eventHooks_ = null; + this.dialog_ = new remoting.MessageDialog( + remoting.AppMode.CLIENT_HOST_NEEDS_UPGRADE, + rootElement.querySelector('.connect-button'), + rootElement.querySelector('.cancel-button')); l10n.localizeElementFromTag( rootElement.querySelector('.host-needs-update-message'), @@ -177,39 +200,13 @@ if (!remoting.Host.needsUpdate(this.host_, webappVersion)) { return Promise.resolve(); } - - this.eventHooks_ = new base.Disposables( - new base.DomEventHook(this.rootElement_.querySelector('.connect-button'), - 'click', this.onOK_.bind(this), false), - new base.DomEventHook(this.rootElement_.querySelector('.cancel-button'), - 'click', this.onCancel_.bind(this), false)); - - base.debug.assert(this.deferred_ === null); - this.deferred_ = new base.Deferred(); - - remoting.setMode(remoting.AppMode.CLIENT_HOST_NEEDS_UPGRADE); - - return this.deferred_.promise(); -}; - -/** @private */ -remoting.HostNeedsUpdateDialog.prototype.cleanup_ = function() { - base.dispose(this.eventHooks_); - this.eventHooks_ = null; - this.deferred_ = null; -}; - - -/** @private */ -remoting.HostNeedsUpdateDialog.prototype.onOK_ = function() { - this.deferred_.resolve(); - this.cleanup_(); -}; - -/** @private */ -remoting.HostNeedsUpdateDialog.prototype.onCancel_ = function() { - this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); - this.cleanup_(); + /** @typedef {remoting.MessageDialog.Result} */ + var Result = remoting.MessageDialog.Result; + return this.dialog_.show().then(function(/** Result */ result) { + if (result === Result.SECONDARY) { + return Promise.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); + } + }); }; /**
diff --git a/remoting/webapp/crd/js/remoting.js b/remoting/webapp/crd/js/remoting.js index f3deae1..34a15c7 100644 --- a/remoting/webapp/crd/js/remoting.js +++ b/remoting/webapp/crd/js/remoting.js
@@ -30,16 +30,10 @@ document.getElementById('statistics')); remoting.formatIq = new remoting.FormatIq(); - remoting.clipboard = new remoting.Clipboard(); var sandbox = /** @type {HTMLIFrameElement} */ (document.getElementById('wcs-sandbox')); remoting.wcsSandbox = new remoting.WcsSandboxContainer(sandbox.contentWindow); - // The plugin's onFocus handler sends a paste command to |window|, because - // it can't send one to the plugin element itself. - window.addEventListener('paste', pluginGotPaste_, false); - window.addEventListener('copy', pluginGotCopy_, false); - remoting.initModalDialogs(); remoting.testEvents = new base.EventSourceImpl(); @@ -65,33 +59,6 @@ }; /** - * Callback function called when the browser window gets a paste operation. - * - * @param {Event} event - * @return {void} Nothing. - */ -function pluginGotPaste_(event) { - if (event && event.clipboardData) { - remoting.clipboard.toHost(event.clipboardData); - } -} - -/** - * Callback function called when the browser window gets a copy operation. - * - * @param {Event} event - * @return {void} Nothing. - */ -function pluginGotCopy_(event) { - if (event && event.clipboardData) { - if (remoting.clipboard.toOs(event.clipboardData)) { - // The default action may overwrite items that we added to clipboardData. - event.preventDefault(); - } - } -} - -/** * Return the current time as a formatted string suitable for logging. * * @return {string} The current time, formatted as [mmdd/hhmmss.xyz]
diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h index a26a166..a747770 100644 --- a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h +++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -5,8 +5,6 @@ #ifndef SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_ #define SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_ -#include <asm/unistd.h> // For __NR_SYSCALL_BASE - #if defined(__x86_64__) #define MIN_SYSCALL 0u @@ -25,15 +23,19 @@ // and a "ghost syscall private to the kernel", cmpxchg, // at |__ARM_NR_BASE+0x00fff0|. // See </arch/arm/include/asm/unistd.h> in the Linux kernel. -#define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE) + +// __NR_SYSCALL_BASE is 0 in thumb and ARM EABI. +#define MIN_SYSCALL 0u #define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u) -#define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE) +// __ARM_NR_BASE is __NR_SYSCALL_BASE + 0xf0000u +#define MIN_PRIVATE_SYSCALL 0xf0000u #define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u) -#define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u) +#define MIN_GHOST_SYSCALL (MIN_PRIVATE_SYSCALL + 0xfff0u) #define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u) #elif defined(__mips__) && (_MIPS_SIM == _ABIO32) +#include <asm/unistd.h> // for __NR_O32_Linux and __NR_Linux_syscalls #define MIN_SYSCALL __NR_O32_Linux #define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_Linux_syscalls) #define MAX_SYSCALL MAX_PUBLIC_SYSCALL
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc index 21fd4d7..d449156 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -9,7 +9,6 @@ #include <sys/syscall.h> #include <unistd.h> -#include "base/basictypes.h" #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "build/build_config.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h index 38e02bf..c64e9941 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h
@@ -5,7 +5,8 @@ #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_ #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SIGSYS_HANDLERS_H_ -#include "base/basictypes.h" +#include <stdint.h> + #include "build/build_config.h" #include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h" #include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc index c081b29..b315f12a 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -11,6 +11,7 @@ #include <linux/net.h> #include <sched.h> #include <signal.h> +#include <stdint.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/prctl.h> @@ -21,7 +22,6 @@ #include <time.h> #include <unistd.h> -#include "base/basictypes.h" #include "base/logging.h" #include "base/macros.h" #include "base/time/time.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h index 1dbd949..5ba6335a 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.h
@@ -5,7 +5,7 @@ #ifndef SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_SETS_H_ #define SANDBOX_LINUX_SECCOMP_BPF_HELPERS_SYSCALL_SETS_H_ -#include "base/basictypes.h" +#include "base/macros.h" #include "build/build_config.h" #include "sandbox/sandbox_export.h"
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc index 27a89598..3b3c8db 100644 --- a/sandbox/linux/seccomp-bpf/syscall.cc +++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -4,7 +4,6 @@ #include "sandbox/linux/seccomp-bpf/syscall.h" -#include <asm/unistd.h> #include <errno.h> #include <stdint.h>
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn index 93c43436..3063f7f 100644 --- a/sandbox/win/BUILD.gn +++ b/sandbox/win/BUILD.gn
@@ -163,6 +163,7 @@ deps = [ "//base", + "//base:base_static", ] if (current_cpu == "x86") { deps += [ ":copy_wow_helper" ]
diff --git a/sandbox/win/src/handle_closer.h b/sandbox/win/src/handle_closer.h index 60473b3..fa65695 100644 --- a/sandbox/win/src/handle_closer.h +++ b/sandbox/win/src/handle_closer.h
@@ -19,8 +19,7 @@ // This is a map of handle-types to names that we need to close in the // target process. A null set means we need to close all handles of the // given type. -typedef std::map<const base::string16, std::set<const base::string16> > - HandleMap; +typedef std::map<const base::string16, std::set<base::string16> > HandleMap; // Type and set of corresponding handle names to close. struct HandleListEntry {
diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc index d2b507d3..2ff1b73 100644 --- a/sandbox/win/src/win_utils.cc +++ b/sandbox/win/src/win_utils.cc
@@ -355,13 +355,14 @@ OBJECT_NAME_INFORMATION* name = &initial_buffer; ULONG size = sizeof(initial_buffer); // Query the name information a first time to get the size of the name. + // Windows XP requires that the size of the buffer passed in here be != 0. NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size, &size); - scoped_ptr<OBJECT_NAME_INFORMATION> name_ptr; + scoped_ptr<BYTE[]> name_ptr; if (size) { - name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(new BYTE[size]); - name_ptr.reset(name); + name_ptr.reset(new BYTE[size]); + name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(name_ptr.get()); // Query the name information a second time to get the name of the // object referenced by the handle.
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index e3c48ca4..e9990e6 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -253,18 +253,10 @@ # define SK_SUPPORT_LEGACY_GETDEVICE #endif -#ifndef SK_SUPPORT_LEGACY_SCALAR_XFERMODES -# define SK_SUPPORT_LEGACY_SCALAR_XFERMODES -#endif - #ifndef SK_SUPPORT_LEGACY_PUBLIC_IMAGEINFO_FIELDS # define SK_SUPPORT_LEGACY_PUBLIC_IMAGEINFO_FIELDS #endif -#ifndef SK_SUPPORT_LEGACY_SCALAR_MAPPOINTS -# define SK_SUPPORT_LEGACY_SCALAR_MAPPOINTS -#endif - #ifndef SK_IGNORE_ETC1_SUPPORT # define SK_IGNORE_ETC1_SUPPORT #endif
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc index 0ff16602..066f35f 100644 --- a/skia/ext/analysis_canvas.cc +++ b/skia/ext/analysis_canvas.cc
@@ -60,7 +60,9 @@ return false; SkIRect clip_irect; - canvas->getClipDeviceBounds(&clip_irect); + if (!canvas->getClipDeviceBounds(&clip_irect)) + return false; + // if the clip is smaller than the canvas, we're partly clipped, so abort. if (!clip_irect.contains(SkIRect::MakeSize(canvas->getDeviceSize()))) return false; @@ -96,8 +98,8 @@ void AnalysisCanvas::onDrawPaint(const SkPaint& paint) { SkRect rect; - getClipBounds(&rect); - drawRect(rect, paint); + if (getClipBounds(&rect)) + drawRect(rect, paint); } void AnalysisCanvas::onDrawPoints(SkCanvas::PointMode mode,
diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc index 8263075b..db8e7a2 100644 --- a/skia/ext/analysis_canvas_unittest.cc +++ b/skia/ext/analysis_canvas_unittest.cc
@@ -183,7 +183,8 @@ skia::AnalysisCanvas canvas(255, 255); SkPaint paint; - skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(SkOffsetImageFilter::Create(10, 10)); + skia::RefPtr<SkImageFilter> filter = + skia::AdoptRef(SkOffsetImageFilter::Create(10, 10)); paint.setImageFilter(filter.get()); canvas.drawRect(SkRect::MakeWH(255, 255), paint); @@ -344,7 +345,8 @@ record_canvas->drawText( text.c_str(), text.length(), point.fX, point.fY, paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(recorder.endRecordingAsPicture()); // Draw the picture into the analysis canvas, using the canvas as a callback // as well. @@ -357,7 +359,6 @@ // Verify that we aborted drawing. EXPECT_TRUE(canvas.abortDrawing()); - } TEST(AnalysisCanvasTest, ClipComplexRegion) {
diff --git a/skia/ext/pixel_ref_utils_unittest.cc b/skia/ext/pixel_ref_utils_unittest.cc index 50aa40d..1e8f6ee 100644 --- a/skia/ext/pixel_ref_utils_unittest.cc +++ b/skia/ext/pixel_ref_utils_unittest.cc
@@ -85,7 +85,7 @@ SkPicture* StopRecording(SkPictureRecorder* recorder, SkCanvas* canvas) { canvas->restore(); - return recorder->endRecording(); + return recorder->endRecordingAsPicture(); } } // namespace @@ -115,7 +115,8 @@ canvas->clipRect(SkRect::MakeWH(100, 100)); canvas->drawPaint(third_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -168,7 +169,8 @@ // (50, 55, 150, 145). canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, third_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -216,7 +218,8 @@ // (50, 50, 50, 50) canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), third_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -269,7 +272,8 @@ // (50, 50, 50, 50) canvas->drawRRect(rrect, third_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -321,7 +325,8 @@ // (50, 50, 50, 50) canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), third_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -365,7 +370,8 @@ canvas->restore(); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -419,7 +425,8 @@ // At (0, 0), scaled by 5 and 6 canvas->drawBitmap(fifth, 0, 0); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -435,7 +442,6 @@ gfx::SkRectToRectF(pixel_refs[3].pixel_ref_rect)); EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 50, 60), gfx::SkRectToRectF(pixel_refs[4].pixel_ref_rect)); - } TEST(PixelRefUtilsTest, DrawBitmapRect) { @@ -473,7 +479,8 @@ canvas->restore(); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -536,7 +543,8 @@ // (100, 100, 50, 50). canvas->drawSprite(fifth, 100, 100, &first_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -583,7 +591,8 @@ canvas->drawPosText("text", 4, points, first_paint); canvas->drawTextOnPath("text", 4, path, NULL, first_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs); @@ -656,7 +665,8 @@ 3, third_paint); - skia::RefPtr<SkPicture> picture = skia::AdoptRef(StopRecording(&recorder, canvas)); + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); std::vector<skia::PixelRefUtils::PositionPixelRef> pixel_refs; skia::PixelRefUtils::GatherDiscardablePixelRefs(picture.get(), &pixel_refs);
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt index c4e1679..b4ab8be9 100644 --- a/skia/skia_test_expectations.txt +++ b/skia/skia_test_expectations.txt
@@ -59,4 +59,43 @@ Bug(senorblanco) virtual/slimmingpaint/css3/filters/filter-repaint-composited-fallback-crash.html [ NeedsManualRebaseline ] Bug(senorblanco) virtual/slimmingpaint/css3/filters/filter-repaint-composited-fallback.html [ NeedsManualRebaseline ] +# SK_SUPPORT_LEGACY_SCALAR_XFERMODES +crbug.com/475017 css3/blending/background-blend-mode-crossfade-image-gradient.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/background-blend-mode-default-value.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/background-blend-mode-gradient-image.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/background-blend-mode-image-color.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/background-blend-mode-image-image.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/background-blend-mode-image-svg.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/background-blend-mode-tiled-gradient.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/effect-background-blend-mode-tiled.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/blending/effect-background-blend-mode.html [ NeedsManualRebaseline ] +crbug.com/475017 css3/filters/effect-reference-composite.html [ NeedsManualRebaseline ] +crbug.com/475017 fast/backgrounds/background-clip-text-composited.html [ NeedsManualRebaseline ] +crbug.com/475017 fast/canvas/canvas-composite-shadow.html [ NeedsManualRebaseline ] +crbug.com/475017 fast/canvas/canvas-composite-transformclip.html [ NeedsManualRebaseline ] +crbug.com/475017 fast/canvas/canvas-composite-video.html [ NeedsManualRebaseline ] +crbug.com/475017 fast/canvas/canvas-composite.html [ NeedsManualRebaseline ] +crbug.com/475017 svg/W3C-SVG-1.1/filters-composite-02-b.svg [ NeedsManualRebaseline ] +crbug.com/475017 svg/custom/massive-coordinates.svg [ NeedsManualRebaseline ] +crbug.com/475017 svg/filters/feComposite.svg [ NeedsManualRebaseline ] +crbug.com/475017 svg/repaint/filter-repaint.svg [ NeedsManualRebaseline ] +crbug.com/475017 virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/display_list_2d_canvas/fast/canvas/canvas-composite-transformclip.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/display_list_2d_canvas/fast/canvas/canvas-composite-video.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/display_list_2d_canvas/fast/canvas/canvas-composite.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/css3/filters/effect-reference-composite.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/fast/backgrounds/background-clip-text-composited.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/fast/canvas/canvas-composite-shadow.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/fast/canvas/canvas-composite-transformclip.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/fast/canvas/canvas-composite-video.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/fast/canvas/canvas-composite.html [ NeedsManualRebaseline ] +crbug.com/475017 virtual/slimmingpaint/svg/filters/feComposite.svg [ NeedsManualRebaseline ] + +# SK_SUPPORT_LEGACY_SCALAR_MAPPOINTS +crbug.com/475022 media/audio-repaint.html [ NeedsManualRebaseline ] +crbug.com/475022 svg/custom/linking-a-03-b-viewBox-transform.svg [ NeedsManualRebaseline ] +crbug.com/475022 svg/custom/marker-orient-auto.html [ NeedsManualRebaseline ] +crbug.com/475022 svg/text/text-path-01-b.svg [ NeedsManualRebaseline ] +crbug.com/475022 virtual/slimmingpaint/svg/text/text-path-01-b.svg [ NeedsManualRebaseline ] + # END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/sql/connection.cc b/sql/connection.cc index cc7e69d..bfe8bb74 100644 --- a/sql/connection.cc +++ b/sql/connection.cc
@@ -725,7 +725,8 @@ int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) { // This is evidence of a syntax error in the incoming SQL. - DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); + DLOG_IF(FATAL, !ShouldIgnoreSqliteError(rc)) + << "SQL compile error " << GetErrorMessage(); // It could also be database corruption. OnSqliteError(rc, NULL, sql); @@ -744,7 +745,8 @@ int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) { // This is evidence of a syntax error in the incoming SQL. - DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); + DLOG_IF(FATAL, !ShouldIgnoreSqliteError(rc)) + << "SQL compile error " << GetErrorMessage(); return new StatementRef(NULL, NULL, false); } return new StatementRef(NULL, stmt, true); @@ -798,8 +800,15 @@ bool Connection::DoesTableOrIndexExist( const char* name, const char* type) const { - const char* kSql = "SELECT name FROM sqlite_master WHERE type=? AND name=?"; + const char* kSql = + "SELECT name FROM sqlite_master WHERE type=? AND name=? COLLATE NOCASE"; Statement statement(GetUntrackedStatement(kSql)); + + // This can happen if the database is corrupt and the error is being ignored + // for testing purposes. + if (!statement.is_valid()) + return false; + statement.BindString(0, type); statement.BindString(1, name); @@ -813,8 +822,14 @@ sql.append(")"); Statement statement(GetUntrackedStatement(sql.c_str())); + + // This can happen if the database is corrupt and the error is being ignored + // for testing purposes. + if (!statement.is_valid()) + return false; + while (statement.Step()) { - if (!statement.ColumnString(1).compare(column_name)) + if (!base::strcasecmp(statement.ColumnString(1).c_str(), column_name)) return true; } return false;
diff --git a/sql/connection.h b/sql/connection.h index 5bbdb97..2f6c71f 100644 --- a/sql/connection.h +++ b/sql/connection.h
@@ -361,10 +361,10 @@ // Info querying ------------------------------------------------------------- - // Returns true if the given table exists. + // Returns true if the given table (or index) exists. Instead of + // test-then-create, callers should almost always prefer "CREATE TABLE IF NOT + // EXISTS" or "CREATE INDEX IF NOT EXISTS". bool DoesTableExist(const char* table_name) const; - - // Returns true if the given index exists. bool DoesIndexExist(const char* index_name) const; // Returns true if a column with the given name exists in the given table.
diff --git a/sql/connection_unittest.cc b/sql/connection_unittest.cc index 07c9fa7..3cb2e37 100644 --- a/sql/connection_unittest.cc +++ b/sql/connection_unittest.cc
@@ -176,10 +176,9 @@ // Test DoesTableExist. EXPECT_FALSE(db().DoesTableExist("foo")); ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)")); EXPECT_TRUE(db().DoesTableExist("foo")); - - // Should be case sensitive. - EXPECT_FALSE(db().DoesTableExist("FOO")); + EXPECT_TRUE(db().DoesIndexExist("foo_a")); // Test DoesColumnExist. EXPECT_FALSE(db().DoesColumnExist("foo", "bar")); @@ -187,6 +186,10 @@ // Testing for a column on a nonexistent table. EXPECT_FALSE(db().DoesColumnExist("bar", "b")); + + // Names are not case sensitive. + EXPECT_TRUE(db().DoesTableExist("FOO")); + EXPECT_TRUE(db().DoesColumnExist("FOO", "A")); } TEST_F(SQLConnectionTest, GetLastInsertRowId) { @@ -221,10 +224,36 @@ ASSERT_TRUE(db().Execute(kCreateSql)); ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); - sql::ScopedErrorIgnorer ignore_errors; - ignore_errors.IgnoreError(SQLITE_CONSTRAINT); - ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); - ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); + { + sql::ScopedErrorIgnorer ignore_errors; + ignore_errors.IgnoreError(SQLITE_CONSTRAINT); + ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); + } +} + +// Test that clients of GetUntrackedStatement() can test corruption-handling +// with ScopedErrorIgnorer. +TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) { + const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; + ASSERT_TRUE(db().Execute(kCreateSql)); + ASSERT_FALSE(db().DoesTableExist("bar")); + ASSERT_TRUE(db().DoesTableExist("foo")); + ASSERT_TRUE(db().DoesColumnExist("foo", "id")); + db().Close(); + + // Corrupt the database so that nothing works, including PRAGMAs. + ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path())); + + { + sql::ScopedErrorIgnorer ignore_errors; + ignore_errors.IgnoreError(SQLITE_CORRUPT); + ASSERT_TRUE(db().Open(db_path())); + ASSERT_FALSE(db().DoesTableExist("bar")); + ASSERT_FALSE(db().DoesTableExist("foo")); + ASSERT_FALSE(db().DoesColumnExist("foo", "id")); + ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); + } } TEST_F(SQLConnectionTest, ErrorCallback) {
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index 1753b559..d4410d7 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn
@@ -645,6 +645,7 @@ "//sql", "//sync", "//sync/internal_api/attachments/proto", + "//sync/protocol", "//testing/gmock", "//testing/gtest", "//third_party/leveldatabase",
diff --git a/sync/protocol/BUILD.gn b/sync/protocol/BUILD.gn index b8258f90..a8da5ac0 100644 --- a/sync/protocol/BUILD.gn +++ b/sync/protocol/BUILD.gn
@@ -4,7 +4,17 @@ import("//third_party/protobuf/proto_library.gni") -proto_library("protocol") { +# This must be a component for the dependency structure we have now, but the +# proto_library generates a source set. Link those into a component. +component("protocol") { + public_deps = [ + ":protocol_internal", + ] +} + +proto_library("protocol_internal") { + visibility = [ ":protocol" ] + sources = [ "app_list_specifics.proto", "app_notification_specifics.proto",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 7a574d8..205e583 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -2286,7 +2286,7 @@ { "args": [ "--site-per-process", - "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort" + "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort" ], "test": "content_browsertests" }, @@ -2316,7 +2316,7 @@ { "args": [ "--site-per-process", - "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort" + "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort" ], "test": "content_browsertests" },
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json index 74746d2..f8782ab01 100644 --- a/testing/commit_queue/config.json +++ b/testing/commit_queue/config.json
@@ -34,12 +34,6 @@ "android_amp_rel_tests_recipe": [ "defaulttests" ], - "cast_shell_android": [ - "defaulttests" - ], - "cast_shell_linux": [ - "defaulttests" - ], "linux_arm_compile": [ "defaulttests" ], @@ -67,7 +61,14 @@ "percentage": 1.0, "trybots": { "launched": { - "tryserver.chromium.linux": {}, + "tryserver.chromium.linux": { + "cast_shell_android": [ + "defaulttests" + ], + "cast_shell_linux": [ + "defaulttests" + ] + }, "tryserver.chromium.mac": {} } }
diff --git a/testing/iossim/iossim.mm b/testing/iossim/iossim.mm index 83cfe92..2f2af8d2 100644 --- a/testing/iossim/iossim.mm +++ b/testing/iossim/iossim.mm
@@ -850,7 +850,8 @@ NSString* appPath = nil; NSString* appName = nil; NSString* sdkVersion = nil; - NSString* deviceName = IsRunningWithXcode6OrLater() ? @"iPhone 5" : @"iPhone"; + NSString* deviceName = + IsRunningWithXcode6OrLater() ? @"iPhone 5s" : @"iPhone"; NSString* simHomePath = nil; NSMutableArray* appArgs = [NSMutableArray array]; NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index 01a423097..3daa61e 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi
@@ -130,6 +130,7 @@ 'src/crypto/evp/digestsign.c', 'src/crypto/evp/evp.c', 'src/crypto/evp/evp_ctx.c', + 'src/crypto/evp/p_dsa_asn1.c', 'src/crypto/evp/p_ec.c', 'src/crypto/evp/p_ec_asn1.c', 'src/crypto/evp/p_hmac.c',
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c index fe8e3d4..54841e30 100644 --- a/third_party/boringssl/err_data.c +++ b/third_party/boringssl/err_data.c
@@ -79,194 +79,202 @@ 0xc3d0679, 0xc3d8681, 0xc3e068c, - 0x103217ce, - 0x103297e5, - 0x103317fe, - 0x10339814, - 0x10341824, - 0x10349837, - 0x10351845, - 0x10359854, - 0x10361874, - 0x10369893, - 0x103718b0, - 0x103798cd, - 0x103818e2, - 0x10389904, - 0x10391923, - 0x10399942, - 0x103a1959, - 0x103a9970, - 0x103b1979, - 0x103b9984, - 0x103c199e, - 0x103c99a6, - 0x103d19ae, - 0x103d99b5, - 0x103e19c8, - 0x103e99da, - 0x103f19ed, - 0x103f99f6, + 0x1032184c, + 0x10329863, + 0x1033187c, + 0x10339892, + 0x103418a2, + 0x103498b5, + 0x103518c3, + 0x103598d2, + 0x103618f2, + 0x10369911, + 0x1037192e, + 0x1037994b, + 0x10381960, + 0x10389982, + 0x103919a1, + 0x103999c0, + 0x103a19d7, + 0x103a99ee, + 0x103b19f7, + 0x103b9a02, + 0x103c1a1c, + 0x103c9a24, + 0x103d1a2c, + 0x103d9a33, + 0x103e1a46, + 0x103e9a58, + 0x103f1a6b, + 0x103f9a74, 0x14320a25, 0x14328a33, 0x14330a3f, 0x14338a4c, - 0x18321065, - 0x1832907d, - 0x1833109f, - 0x183390b1, - 0x183410e3, - 0x183490fc, - 0x1835110d, - 0x18359123, 0x18361133, - 0x18369148, 0x18371161, 0x18379172, 0x18381188, - 0x18389199, 0x183911ab, 0x183991c0, 0x183a11d2, - 0x183a91e2, - 0x183b11f7, - 0x183b9204, 0x183c1216, 0x183c9224, 0x183d1237, 0x183d9247, - 0x183e125c, 0x183e926d, 0x183f1280, 0x183f928f, - 0x1840129f, - 0x184092ac, - 0x184112bb, - 0x184192cc, - 0x184212df, - 0x184292f1, - 0x18431303, - 0x18439314, - 0x18441325, - 0x18449336, - 0x18451347, - 0x18459354, - 0x18461362, - 0x18469375, - 0x18471389, - 0x18479396, - 0x184813a5, - 0x184893b4, - 0x184913c5, - 0x184993e1, - 0x184a13ef, - 0x184a9400, - 0x184b1411, - 0x184b941f, - 0x184c142f, - 0x184c9455, - 0x184d1464, - 0x184d9474, - 0x184e1484, - 0x184e9493, - 0x184f13d2, + 0x184092b9, + 0x18411325, + 0x18419336, + 0x18421349, + 0x1842935b, + 0x1843136d, + 0x1843937e, + 0x1844138f, + 0x184493a0, + 0x184513b1, + 0x184593be, + 0x184613e0, + 0x184693f3, + 0x18471407, + 0x18479414, + 0x18481423, + 0x18489432, + 0x18491443, + 0x1849945f, + 0x184a146d, + 0x184a947e, + 0x184b148f, + 0x184b949d, + 0x184c14ad, + 0x184c94d3, + 0x184d14e2, + 0x184d94f2, + 0x184e1502, + 0x184e9511, + 0x184f1450, 0x184f90c2, + 0x18501065, + 0x1850907d, + 0x1851109f, + 0x185190b1, + 0x185210e3, + 0x185290fc, + 0x1853110d, + 0x18539123, + 0x18541148, + 0x18549199, + 0x185511e2, + 0x185591f7, + 0x18561204, + 0x1856925c, + 0x1857129f, + 0x185792ac, + 0x185812c8, + 0x185892d9, + 0x185912e9, + 0x185992f9, + 0x185a1308, + 0x185a9317, + 0x185b13cc, 0x1c320699, 0x1c3286a5, 0x1c3306b0, 0x1c3386bc, - 0x203214a7, - 0x203294b2, - 0x203314ba, - 0x203394c6, - 0x243214d2, - 0x243294e0, - 0x243314f2, - 0x24339501, - 0x24341514, - 0x24349527, - 0x2435153e, - 0x24359556, - 0x24361564, - 0x2436957c, - 0x24371585, - 0x24379597, - 0x243815ab, - 0x243895b8, - 0x243915ce, - 0x243995e6, - 0x243a15fe, - 0x243a9608, - 0x243b161d, - 0x243b962b, - 0x243c1643, - 0x243c965a, - 0x243d1665, - 0x243d9673, + 0x20321525, + 0x20329530, + 0x20331538, + 0x20339544, + 0x24321550, + 0x2432955e, + 0x24331570, + 0x2433957f, + 0x24341592, + 0x243495a5, + 0x243515bc, + 0x243595d4, + 0x243615e2, + 0x243695fa, + 0x24371603, + 0x24379615, + 0x24381629, + 0x24389636, + 0x2439164c, + 0x24399664, + 0x243a167c, + 0x243a9686, + 0x243b169b, + 0x243b96a9, + 0x243c16c1, + 0x243c96d8, + 0x243d16e3, + 0x243d96f1, 0x28320a85, 0x28328a94, 0x28330a9f, 0x28338aa4, 0x28340aaf, - 0x2c3228da, - 0x2c32a8e6, - 0x2c3328f9, - 0x2c33a90a, - 0x2c342923, - 0x2c34a94b, - 0x2c352962, - 0x2c35a97f, - 0x2c36299c, - 0x2c36a9b9, - 0x2c3729d2, - 0x2c37a9eb, - 0x2c382a01, - 0x2c38aa0f, - 0x2c392a21, - 0x2c39aa3e, - 0x2c3a2a5b, - 0x2c3aaa69, - 0x2c3b2a87, - 0x2c3baaa5, - 0x2c3c2ac0, - 0x2c3caad4, - 0x2c3d2ae6, - 0x2c3daaf6, - 0x2c3e2b04, - 0x2c3eab14, - 0x2c3f2b24, - 0x2c3fab3f, - 0x2c402b50, - 0x2c40ab6b, - 0x2c412b7f, - 0x2c41ab92, - 0x2c422bb1, - 0x2c42abc5, - 0x2c432bd8, - 0x2c43abe7, - 0x2c442bf6, - 0x2c44ac0d, - 0x2c452c28, - 0x2c45ac40, - 0x2c462c54, - 0x2c46ac67, - 0x2c472c78, - 0x2c47ac89, - 0x2c482c9a, - 0x2c48acab, - 0x2c492cba, - 0x2c49acc7, - 0x2c4a2cd4, - 0x2c4aace1, - 0x2c4b2cea, - 0x2c4bacfe, - 0x2c4c2d0d, - 0x2c4cad1b, - 0x2c4d2d3d, - 0x2c4dad4e, - 0x2c4e2d5f, - 0x2c4ead2a, - 0x2c4f293c, + 0x2c322985, + 0x2c32a991, + 0x2c3329a4, + 0x2c33a9b5, + 0x2c3429ce, + 0x2c34a9f6, + 0x2c352a0d, + 0x2c35aa2a, + 0x2c362a47, + 0x2c36aa64, + 0x2c372a7d, + 0x2c37aa96, + 0x2c382aac, + 0x2c38aaba, + 0x2c392acc, + 0x2c39aae9, + 0x2c3a2b06, + 0x2c3aab14, + 0x2c3b2b32, + 0x2c3bab50, + 0x2c3c2b6b, + 0x2c3cab7f, + 0x2c3d2b91, + 0x2c3daba1, + 0x2c3e2baf, + 0x2c3eabbf, + 0x2c3f2bcf, + 0x2c3fabea, + 0x2c402bfb, + 0x2c40ac16, + 0x2c412c2a, + 0x2c41ac3d, + 0x2c422c5c, + 0x2c42ac70, + 0x2c432c83, + 0x2c43ac92, + 0x2c442ca1, + 0x2c44acb8, + 0x2c452cd3, + 0x2c45aceb, + 0x2c462cff, + 0x2c46ad12, + 0x2c472d23, + 0x2c47ad34, + 0x2c482d45, + 0x2c48ad56, + 0x2c492d65, + 0x2c49ad72, + 0x2c4a2d7f, + 0x2c4aad8c, + 0x2c4b2d95, + 0x2c4bada9, + 0x2c4c2db8, + 0x2c4cadc6, + 0x2c4d2de8, + 0x2c4dadf9, + 0x2c4e2e0a, + 0x2c4eadd5, + 0x2c4f29e7, 0x30320000, 0x30328018, 0x3033002c, @@ -398,172 +406,174 @@ 0x3c4e0fd6, 0x3c4e8fe7, 0x3c4f0ff7, - 0x40321a01, - 0x40329a1b, - 0x40331a27, - 0x40339a3f, - 0x40341a5d, - 0x40349a7c, - 0x40351a93, - 0x40359aaf, - 0x40361acb, - 0x40369ae5, - 0x40371b04, - 0x40379b23, - 0x40381b3b, - 0x40389b58, - 0x40391b7b, - 0x40399b98, - 0x403a1bb6, - 0x403a9bc6, - 0x403b1bdb, - 0x403b9bf7, - 0x403c1c11, - 0x403c9c1c, - 0x403d1c3f, - 0x403d9c63, - 0x403e1c79, - 0x403e9c83, - 0x403f1c8f, - 0x403f9ca0, - 0x40401cb8, - 0x40409cc0, - 0x40411cc9, - 0x40419cd2, - 0x40421ce2, - 0x40429cf6, - 0x40431d01, - 0x40439d0d, - 0x40441d28, - 0x40449d34, - 0x40451d41, - 0x40459d54, - 0x40461d6c, - 0x40469d84, - 0x40471d9a, - 0x40479db5, - 0x40481dd0, - 0x40489de4, - 0x40491dfd, - 0x40499e16, - 0x404a1e30, - 0x404a9e3a, - 0x404b1e4a, - 0x404b9e6b, - 0x404c1e86, - 0x404c9e94, - 0x404d1ea1, - 0x404d9eb5, - 0x404e1ecd, - 0x404e9edb, - 0x404f1f05, - 0x404f9f1c, - 0x40501f2e, - 0x40509f5f, - 0x40511f90, - 0x40519fa5, - 0x40521fb6, - 0x40529fd6, - 0x40531ff1, - 0x4053a001, - 0x4054200d, - 0x4054a020, - 0x40552036, - 0x4055a054, - 0x40562061, - 0x4056a06b, - 0x40572079, - 0x4057a094, - 0x405820af, - 0x4058a0ce, - 0x405920e3, - 0x4059a0f8, - 0x405a2115, - 0x405aa129, - 0x405b2145, - 0x405ba15b, - 0x405c2178, - 0x405ca18a, - 0x405d21a1, - 0x405da1b2, - 0x405e21ce, - 0x405ea1e2, - 0x405f21f2, - 0x405fa20e, - 0x40602223, - 0x4060a239, - 0x40612256, - 0x4061a26f, - 0x40622282, - 0x4062a28b, - 0x4063229b, - 0x4063a2a7, - 0x406422bd, - 0x4064a2db, - 0x406522f0, - 0x4065a30d, - 0x40662324, - 0x4066a342, - 0x4067235f, - 0x4067a376, - 0x40682394, - 0x4068a3ab, - 0x406923c3, - 0x4069a3d4, - 0x406a23e7, - 0x406aa3fa, - 0x406b240e, - 0x406ba432, - 0x406c244d, - 0x406ca46e, - 0x406d2492, - 0x406da4ad, - 0x406e24ce, - 0x406ea4e3, - 0x406f24fc, - 0x406fa509, - 0x40702517, - 0x4070a524, - 0x40712541, - 0x4071a561, - 0x4072257c, - 0x4072a595, - 0x407325ac, - 0x4073a5c6, - 0x407425ea, - 0x4074a600, - 0x40752614, - 0x4075a629, - 0x40762643, - 0x4076a655, - 0x4077266a, - 0x4077a690, - 0x407826ad, - 0x4078a6d0, - 0x407926f6, - 0x4079a713, - 0x407a2736, - 0x407aa752, - 0x407b276e, - 0x407ba780, - 0x407c278d, - 0x407ca79a, - 0x407d27b7, - 0x407da7ce, - 0x407e27ea, - 0x407ea800, - 0x407f2818, - 0x407fa82b, - 0x40802840, - 0x4080a859, - 0x40812877, - 0x4081a897, - 0x408228a0, - 0x4082a8bc, - 0x408328c5, - 0x40839eea, - 0x40841f79, - 0x40849f49, + 0x40321a7f, + 0x40329a99, + 0x40331aa5, + 0x40339abd, + 0x40341adb, + 0x40349afa, + 0x40351b11, + 0x40359b2d, + 0x40361b49, + 0x40369b63, + 0x40371b82, + 0x40379ba1, + 0x40381bb9, + 0x40389bd6, + 0x40391bf9, + 0x40399c16, + 0x403a1c34, + 0x403a9c44, + 0x403b1c59, + 0x403b9c75, + 0x403c1c8f, + 0x403c9c9a, + 0x403d1cbd, + 0x403d9ce1, + 0x403e1cf7, + 0x403e9d01, + 0x403f1d0d, + 0x403f9d1e, + 0x40401d36, + 0x40409d3e, + 0x40411d47, + 0x40419d50, + 0x40421d60, + 0x40429d74, + 0x40431d7f, + 0x40439d8b, + 0x40441da6, + 0x40449db2, + 0x40451dbf, + 0x40459dd2, + 0x40461dea, + 0x40469e02, + 0x40471e18, + 0x40479e33, + 0x40481e4e, + 0x40489e62, + 0x40491e7b, + 0x40499e94, + 0x404a1eae, + 0x404a9eb8, + 0x404b1ec8, + 0x404b9ee9, + 0x404c1f04, + 0x404c9f12, + 0x404d1f1f, + 0x404d9f33, + 0x404e1f4b, + 0x404e9f59, + 0x404f1f83, + 0x404f9f9a, + 0x40501fac, + 0x40509fdd, + 0x4051200e, + 0x4051a023, + 0x40522034, + 0x4052a054, + 0x4053206f, + 0x4053a07f, + 0x4054208b, + 0x4054a09e, + 0x405520b4, + 0x4055a0d2, + 0x405620df, + 0x4056a0e9, + 0x405720f7, + 0x4057a112, + 0x4058212d, + 0x4058a14c, + 0x40592161, + 0x4059a176, + 0x405a2193, + 0x405aa1a7, + 0x405b21c3, + 0x405ba1d9, + 0x405c21f6, + 0x405ca208, + 0x405d221f, + 0x405da230, + 0x405e224c, + 0x405ea260, + 0x405f2270, + 0x405fa28c, + 0x406022a1, + 0x4060a2b7, + 0x406122d4, + 0x4061a2ed, + 0x40622300, + 0x4062a309, + 0x40632319, + 0x4063a352, + 0x40642368, + 0x4064a386, + 0x4065239b, + 0x4065a3b8, + 0x406623cf, + 0x4066a3ed, + 0x4067240a, + 0x4067a421, + 0x4068243f, + 0x4068a456, + 0x4069246e, + 0x4069a47f, + 0x406a2492, + 0x406aa4a5, + 0x406b24b9, + 0x406ba4dd, + 0x406c24f8, + 0x406ca519, + 0x406d253d, + 0x406da558, + 0x406e2579, + 0x406ea58e, + 0x406f25a7, + 0x406fa5b4, + 0x407025c2, + 0x4070a5cf, + 0x407125ec, + 0x4071a60c, + 0x40722627, + 0x4072a640, + 0x40732657, + 0x4073a671, + 0x40742695, + 0x4074a6ab, + 0x407526bf, + 0x4075a6d4, + 0x407626ee, + 0x4076a700, + 0x40772715, + 0x4077a73b, + 0x40782758, + 0x4078a77b, + 0x407927a1, + 0x4079a7be, + 0x407a27e1, + 0x407aa7fd, + 0x407b2819, + 0x407ba82b, + 0x407c2838, + 0x407ca845, + 0x407d2862, + 0x407da879, + 0x407e2895, + 0x407ea8ab, + 0x407f28c3, + 0x407fa8d6, + 0x408028eb, + 0x4080a904, + 0x40812922, + 0x4081a942, + 0x4082294b, + 0x4082a967, + 0x40832970, + 0x40839f68, + 0x40841ff7, + 0x40849fc7, + 0x40852341, + 0x4085a325, 0x4432042a, 0x4432843c, 0x44330445, @@ -582,81 +592,81 @@ 0x44398522, 0x443a052c, 0x443a8536, - 0x4c32167b, - 0x4c32968a, - 0x4c331699, - 0x4c3396b2, - 0x4c3416cd, - 0x4c3496e9, - 0x4c3516fb, - 0x4c359709, - 0x4c36171e, - 0x4c36972f, - 0x4c37173d, - 0x4c37974b, - 0x4c38175d, - 0x4c38976d, - 0x4c391777, - 0x4c39978f, - 0x4c3a17a7, - 0x4c3a97ba, - 0x50322d70, - 0x5032ad85, - 0x50332d96, - 0x5033ada9, - 0x50342dba, - 0x5034adcd, - 0x50352ddc, - 0x5035adf1, - 0x50362e01, - 0x5036ae10, - 0x50372e21, - 0x5037ae31, - 0x50382e42, - 0x5038ae55, - 0x50392e67, - 0x5039ae7d, - 0x503a2e8f, - 0x503aaea0, - 0x503b2eb1, - 0x503baec2, - 0x503c2ecd, - 0x503caed9, - 0x503d2ee4, - 0x503daeef, - 0x503e2efc, - 0x503eaf11, - 0x503f2f1f, - 0x503faf33, - 0x50402f46, - 0x5040af57, - 0x50412f71, - 0x5041af80, - 0x50422f89, - 0x5042af98, - 0x50432faa, - 0x5043afb6, - 0x50442fbe, - 0x5044afd1, - 0x50452fe2, - 0x5045aff8, - 0x50463004, - 0x5046b018, - 0x50473026, - 0x5047b03a, - 0x50483054, - 0x5048b068, - 0x5049307e, - 0x5049b095, - 0x504a30a7, - 0x504ab0bb, - 0x504b30d0, - 0x504bb0e7, - 0x504c30fb, - 0x504cb104, - 0x504d310c, - 0x504db11b, - 0x504e312b, + 0x4c3216f9, + 0x4c329708, + 0x4c331717, + 0x4c339730, + 0x4c34174b, + 0x4c349767, + 0x4c351779, + 0x4c359787, + 0x4c36179c, + 0x4c3697ad, + 0x4c3717bb, + 0x4c3797c9, + 0x4c3817db, + 0x4c3897eb, + 0x4c3917f5, + 0x4c39980d, + 0x4c3a1825, + 0x4c3a9838, + 0x50322e1b, + 0x5032ae30, + 0x50332e41, + 0x5033ae54, + 0x50342e65, + 0x5034ae78, + 0x50352e87, + 0x5035ae9c, + 0x50362eac, + 0x5036aebb, + 0x50372ecc, + 0x5037aedc, + 0x50382eed, + 0x5038af00, + 0x50392f12, + 0x5039af28, + 0x503a2f3a, + 0x503aaf4b, + 0x503b2f5c, + 0x503baf6d, + 0x503c2f78, + 0x503caf84, + 0x503d2f8f, + 0x503daf9a, + 0x503e2fa7, + 0x503eafbc, + 0x503f2fca, + 0x503fafde, + 0x50402ff1, + 0x5040b002, + 0x5041301c, + 0x5041b02b, + 0x50423034, + 0x5042b043, + 0x50433055, + 0x5043b061, + 0x50443069, + 0x5044b07c, + 0x5045308d, + 0x5045b0a3, + 0x504630af, + 0x5046b0c3, + 0x504730d1, + 0x5047b0e5, + 0x504830ff, + 0x5048b113, + 0x50493129, + 0x5049b140, + 0x504a3152, + 0x504ab166, + 0x504b317b, + 0x504bb192, + 0x504c31a6, + 0x504cb1af, + 0x504d31b7, + 0x504db1c6, + 0x504e31d6, 0x68321018, 0x68329029, 0x68331039, @@ -700,7 +710,7 @@ 0x784207a0, 0x784287be, 0x784307dc, - 0x803214a2, + 0x80321520, }; const size_t kOpenSSLFunctionValuesLen = sizeof(kOpenSSLFunctionValues) / sizeof(kOpenSSLFunctionValues[0]); @@ -965,8 +975,15 @@ "d2i_AutoPrivateKey\0" "d2i_PrivateKey\0" "do_EC_KEY_print\0" + "do_dsa_print\0" "do_rsa_print\0" "do_sigver_init\0" + "dsa_param_decode\0" + "dsa_priv_decode\0" + "dsa_priv_encode\0" + "dsa_pub_decode\0" + "dsa_pub_encode\0" + "dsa_sig_print\0" "eckey_param2type\0" "eckey_param_decode\0" "eckey_priv_decode\0" @@ -977,6 +994,7 @@ "evp_pkey_ctx_new\0" "hmac_signctx\0" "i2d_PublicKey\0" + "old_dsa_priv_decode\0" "old_ec_priv_decode\0" "old_rsa_priv_decode\0" "pkey_ec_ctrl\0" @@ -1173,6 +1191,8 @@ "ssl3_prf\0" "ssl3_read_bytes\0" "ssl3_read_n\0" + "ssl3_record_sequence_update\0" + "ssl3_seal_record\0" "ssl3_send_cert_verify\0" "ssl3_send_certificate_request\0" "ssl3_send_channel_id\0" @@ -1373,152 +1393,154 @@ 0xc3908a5, 0xc3988b4, 0xc3a08c8, - 0x10321417, - 0x10329423, - 0x1033143c, - 0x1033944f, + 0x10321440, + 0x1032944c, + 0x10331465, + 0x10339478, 0x10340da9, - 0x10349462, - 0x10351477, - 0x1035948a, - 0x103614a3, - 0x103694b8, - 0x103714d6, - 0x103794e5, - 0x10381501, - 0x1038951c, - 0x1039152b, - 0x10399547, - 0x103a1562, - 0x103a9579, - 0x103b158a, - 0x103b959e, - 0x103c15bd, - 0x103c95cc, - 0x103d15e3, - 0x103d95f6, + 0x1034948b, + 0x103514a0, + 0x103594b3, + 0x103614cc, + 0x103694e1, + 0x103714ff, + 0x1037950e, + 0x1038152a, + 0x10389545, + 0x10391554, + 0x10399570, + 0x103a158b, + 0x103a95a2, + 0x103b15b3, + 0x103b95c7, + 0x103c15e6, + 0x103c95f5, + 0x103d160c, + 0x103d961f, 0x103e0b5f, - 0x103e9609, - 0x103f161c, - 0x103f9636, - 0x10401646, - 0x1040965a, - 0x10411670, - 0x10419688, - 0x1042169d, - 0x104296b1, - 0x104316c3, + 0x103e9632, + 0x103f1645, + 0x103f965f, + 0x1040166f, + 0x10409683, + 0x10411699, + 0x104196b1, + 0x104216c6, + 0x104296da, + 0x104316ec, 0x104385d0, 0x104408b4, - 0x104496d8, - 0x104516ef, - 0x10459704, - 0x10461712, + 0x10449701, + 0x10451718, + 0x1045972d, + 0x1046173b, 0x14320b42, 0x14328b50, 0x14330b5f, 0x14338b71, 0x18320083, - 0x18328dff, - 0x18330e15, - 0x18338094, - 0x18340e2d, - 0x18348e41, - 0x18350e56, - 0x18358e78, - 0x18360e90, - 0x18368ea5, - 0x18370eb8, - 0x18378ecc, - 0x18380ef0, - 0x18388efe, - 0x18390f14, - 0x18398f28, - 0x183a0f38, - 0x183a89cc, - 0x183b0f48, - 0x183b8f5d, - 0x183c0f74, - 0x183c8f88, - 0x183d0f9c, - 0x183d8fac, + 0x18328e0f, + 0x18340e3d, + 0x18348e51, + 0x18358e88, + 0x18368eb5, + 0x18370ec8, + 0x18378edc, + 0x18380f00, + 0x18388f0e, + 0x18390f24, + 0x18398f38, + 0x183a0f48, + 0x183b0f58, + 0x183b8f6d, + 0x183c8f98, + 0x183d0fac, + 0x183d8fbc, 0x183e0b8e, - 0x183e8fb9, - 0x183f0fcb, - 0x183f8fd6, - 0x18400fe6, - 0x18408ff7, - 0x18411008, - 0x1841901a, - 0x18421043, - 0x1842905c, - 0x1843106b, - 0x1843907f, - 0x184410a0, - 0x184490b8, - 0x184510d4, - 0x184590ea, - 0x18461105, - 0x1846866b, - 0x18471120, - 0x1847913b, - 0x20321162, - 0x2432116e, + 0x183e8fc9, + 0x183f0fdb, + 0x183f8fe6, + 0x18400ff6, + 0x18409007, + 0x18411018, + 0x1841902a, + 0x18421053, + 0x18429085, + 0x18431094, + 0x184510fd, + 0x18459113, + 0x1846112e, + 0x18468ea0, + 0x184709cc, + 0x18478094, + 0x18480f84, + 0x184890c9, + 0x18490e25, + 0x18498e66, + 0x184a1164, + 0x184a90e1, + 0x184b10a8, + 0x184b8dff, + 0x184c106c, + 0x184c866b, + 0x184d1149, + 0x2032118b, + 0x24321197, 0x243288fa, - 0x24331180, - 0x2433918d, - 0x2434119a, - 0x243491ac, - 0x243511bb, - 0x243591d8, - 0x243611e5, - 0x243691f3, - 0x24371201, - 0x2437920f, - 0x24381218, - 0x24389225, - 0x24391238, + 0x243311a9, + 0x243391b6, + 0x243411c3, + 0x243491d5, + 0x243511e4, + 0x24359201, + 0x2436120e, + 0x2436921c, + 0x2437122a, + 0x24379238, + 0x24381241, + 0x2438924e, + 0x24391261, 0x28320b82, 0x28328b8e, 0x28330b5f, 0x28338ba1, - 0x2c3229d2, - 0x2c32a9e0, - 0x2c3329f2, - 0x2c33aa04, - 0x2c342a18, - 0x2c34aa2a, - 0x2c352a45, - 0x2c35aa57, - 0x2c362a6a, + 0x2c322a1c, + 0x2c32aa2a, + 0x2c332a3c, + 0x2c33aa4e, + 0x2c342a62, + 0x2c34aa74, + 0x2c352a8f, + 0x2c35aaa1, + 0x2c362ab4, 0x2c3682f3, - 0x2c372a77, - 0x2c37aa89, - 0x2c382a9c, - 0x2c38aaaa, - 0x2c392aba, - 0x2c39aacc, - 0x2c3a2ae0, - 0x2c3aaaf1, - 0x2c3b12f8, - 0x2c3bab02, - 0x2c3c2b16, - 0x2c3cab2c, - 0x2c3d2b45, - 0x2c3dab73, - 0x2c3e2b81, - 0x2c3eab99, - 0x2c3f2bb1, - 0x2c3fabbe, - 0x2c402be1, - 0x2c40ac00, - 0x2c411162, - 0x2c41ac11, - 0x2c422c24, - 0x2c4290d4, - 0x2c432c35, + 0x2c372ac1, + 0x2c37aad3, + 0x2c382ae6, + 0x2c38aaf4, + 0x2c392b04, + 0x2c39ab16, + 0x2c3a2b2a, + 0x2c3aab3b, + 0x2c3b1321, + 0x2c3bab4c, + 0x2c3c2b60, + 0x2c3cab76, + 0x2c3d2b8f, + 0x2c3dabbd, + 0x2c3e2bcb, + 0x2c3eabe3, + 0x2c3f2bfb, + 0x2c3fac08, + 0x2c402c2b, + 0x2c40ac4a, + 0x2c41118b, + 0x2c41ac5b, + 0x2c422c6e, + 0x2c4290fd, + 0x2c432c7f, 0x2c4386a2, - 0x2c442b62, + 0x2c442bac, 0x30320000, 0x30328015, 0x3033001f, @@ -1639,208 +1661,210 @@ 0x3c3d8d5d, 0x3c3e0d6b, 0x3c3e8d79, - 0x40321729, - 0x4032973f, - 0x4033176d, - 0x40339777, - 0x4034178e, - 0x403497ac, - 0x403517bc, - 0x403597ce, - 0x403617db, - 0x403697e7, - 0x403717fc, - 0x40379811, - 0x40381823, - 0x4038982e, - 0x40391840, + 0x40321752, + 0x40329768, + 0x40331796, + 0x403397a0, + 0x403417b7, + 0x403497d5, + 0x403517e5, + 0x403597f7, + 0x40361804, + 0x40369810, + 0x40371825, + 0x4037983a, + 0x4038184c, + 0x40389857, + 0x40391869, 0x40398da9, - 0x403a1850, - 0x403a9863, - 0x403b1884, - 0x403b9895, - 0x403c18a5, + 0x403a1879, + 0x403a988c, + 0x403b18ad, + 0x403b98be, + 0x403c18ce, 0x403c8064, - 0x403d18b1, - 0x403d98cd, - 0x403e18e3, - 0x403e98f2, - 0x403f1905, - 0x403f991f, - 0x4040192d, - 0x40409942, - 0x40411956, - 0x40419973, - 0x4042198c, - 0x404299a7, - 0x404319c0, - 0x404399d3, - 0x404419e7, - 0x404499ff, - 0x40451a0f, - 0x40459a1d, - 0x40461a3b, + 0x403d18da, + 0x403d98f6, + 0x403e190c, + 0x403e991b, + 0x403f192e, + 0x403f9948, + 0x40401956, + 0x4040996b, + 0x4041197f, + 0x4041999c, + 0x404219b5, + 0x404299d0, + 0x404319e9, + 0x404399fc, + 0x40441a10, + 0x40449a28, + 0x40451a38, + 0x40459a46, + 0x40461a64, 0x40468094, - 0x40471a50, - 0x40479a62, - 0x40481a86, - 0x40489aa6, - 0x40491aba, - 0x40499acf, - 0x404a1ae8, - 0x404a9b0b, - 0x404b1b25, - 0x404b9b43, - 0x404c1b5e, - 0x404c9b78, - 0x404d1b8f, - 0x404d9bb7, - 0x404e1bce, - 0x404e9bea, - 0x404f1c06, - 0x404f9c27, - 0x40501c49, - 0x40509c65, - 0x40511c79, - 0x40519c86, - 0x40521c9d, - 0x40529cad, - 0x40531cbd, - 0x40539cd1, - 0x40541cec, - 0x40549cfc, - 0x40551d13, - 0x40559d22, - 0x40561d3d, - 0x40569d55, - 0x40571d71, - 0x40579d8a, - 0x40581d9d, - 0x40589db2, - 0x40591dd5, - 0x40599de3, - 0x405a1df0, - 0x405a9e09, - 0x405b1e21, - 0x405b9e34, - 0x405c1e49, - 0x405c9e5b, - 0x405d1e70, - 0x405d9e80, - 0x405e1e99, - 0x405e9ead, - 0x405f1ebd, - 0x405f9ed5, - 0x40601ee6, - 0x40609ef9, - 0x40611f0a, - 0x40619f28, - 0x40621f39, - 0x40629f46, - 0x40631f5d, - 0x40639f7d, - 0x40641f94, - 0x40649fa1, - 0x40651faf, - 0x40659fd1, - 0x40661ff9, - 0x4066a00e, - 0x40672025, - 0x4067a036, - 0x40682047, - 0x4068a058, - 0x4069206d, - 0x4069a084, - 0x406a2095, - 0x406aa0ae, - 0x406b20c9, - 0x406ba0e0, - 0x406c20f8, - 0x406ca119, - 0x406d212c, - 0x406da14d, - 0x406e2168, - 0x406ea183, - 0x406f21a4, - 0x406fa1ca, - 0x407021ea, - 0x4070a206, - 0x40712393, - 0x4071a3b6, - 0x407223cc, - 0x4072a3eb, - 0x40732403, - 0x4073a423, - 0x4074264d, - 0x4074a672, - 0x4075268d, - 0x4075a6ac, - 0x407626db, - 0x4076a703, - 0x4077271c, - 0x4077a73b, - 0x40782760, - 0x4078a777, - 0x4079278a, - 0x4079a7a7, + 0x40471a79, + 0x40479a8b, + 0x40481aaf, + 0x40489acf, + 0x40491ae3, + 0x40499af8, + 0x404a1b11, + 0x404a9b34, + 0x404b1b4e, + 0x404b9b6c, + 0x404c1b87, + 0x404c9ba1, + 0x404d1bb8, + 0x404d9be0, + 0x404e1bf7, + 0x404e9c13, + 0x404f1c2f, + 0x404f9c50, + 0x40501c72, + 0x40509c8e, + 0x40511ca2, + 0x40519caf, + 0x40521cc6, + 0x40529cd6, + 0x40531ce6, + 0x40539cfa, + 0x40541d15, + 0x40549d25, + 0x40551d3c, + 0x40559d4b, + 0x40561d66, + 0x40569d7e, + 0x40571d9a, + 0x40579db3, + 0x40581dc6, + 0x40589ddb, + 0x40591dfe, + 0x40599e0c, + 0x405a1e19, + 0x405a9e32, + 0x405b1e4a, + 0x405b9e5d, + 0x405c1e72, + 0x405c9e84, + 0x405d1e99, + 0x405d9ea9, + 0x405e1ec2, + 0x405e9ed6, + 0x405f1ee6, + 0x405f9efe, + 0x40601f0f, + 0x40609f22, + 0x40611f33, + 0x40619f51, + 0x40621f62, + 0x40629f6f, + 0x40631f86, + 0x40639fc7, + 0x40641fde, + 0x40649feb, + 0x40651ff9, + 0x4065a01b, + 0x40662043, + 0x4066a058, + 0x4067206f, + 0x4067a080, + 0x40682091, + 0x4068a0a2, + 0x406920b7, + 0x4069a0ce, + 0x406a20df, + 0x406aa0f8, + 0x406b2113, + 0x406ba12a, + 0x406c2142, + 0x406ca163, + 0x406d2176, + 0x406da197, + 0x406e21b2, + 0x406ea1cd, + 0x406f21ee, + 0x406fa214, + 0x40702234, + 0x4070a250, + 0x407123dd, + 0x4071a400, + 0x40722416, + 0x4072a435, + 0x4073244d, + 0x4073a46d, + 0x40742697, + 0x4074a6bc, + 0x407526d7, + 0x4075a6f6, + 0x40762725, + 0x4076a74d, + 0x40772766, + 0x4077a785, + 0x407827aa, + 0x4078a7c1, + 0x407927d4, + 0x4079a7f1, 0x407a0782, - 0x407aa7b9, - 0x407b27cc, - 0x407ba7e5, - 0x407c27fd, - 0x407c905c, - 0x407d2811, - 0x407da82b, - 0x407e283c, - 0x407ea850, - 0x407f285e, - 0x407fa879, - 0x40801225, - 0x4080a89e, - 0x408128c0, - 0x4081a8db, - 0x408228f0, - 0x4082a908, - 0x40832920, - 0x4083a937, - 0x4084294d, - 0x4084a959, - 0x4085296c, - 0x4085a981, - 0x40862993, - 0x4086a9a8, - 0x408729b1, - 0x40879ba5, - 0x41f422be, - 0x41f92350, - 0x41fe2243, - 0x41fea474, - 0x41ff2565, - 0x420322d7, - 0x420822f9, - 0x4208a335, - 0x42092227, - 0x4209a36f, - 0x420a227e, - 0x420aa25e, - 0x420b229e, - 0x420ba317, - 0x420c2581, - 0x420ca441, - 0x420d245b, - 0x420da492, - 0x421224ac, - 0x42172548, - 0x4217a4ee, - 0x421c2510, - 0x421f24cb, - 0x42212598, - 0x4226252b, - 0x422b2631, - 0x422ba5fa, - 0x422c2619, - 0x422ca5d4, - 0x422d25b3, + 0x407aa803, + 0x407b2816, + 0x407ba82f, + 0x407c2847, + 0x407c9085, + 0x407d285b, + 0x407da875, + 0x407e2886, + 0x407ea89a, + 0x407f28a8, + 0x407fa8c3, + 0x4080124e, + 0x4080a8e8, + 0x4081290a, + 0x4081a925, + 0x4082293a, + 0x4082a952, + 0x4083296a, + 0x4083a981, + 0x40842997, + 0x4084a9a3, + 0x408529b6, + 0x4085a9cb, + 0x408629dd, + 0x4086a9f2, + 0x408729fb, + 0x40879bce, + 0x40880083, + 0x40889fa6, + 0x41f42308, + 0x41f9239a, + 0x41fe228d, + 0x41fea4be, + 0x41ff25af, + 0x42032321, + 0x42082343, + 0x4208a37f, + 0x42092271, + 0x4209a3b9, + 0x420a22c8, + 0x420aa2a8, + 0x420b22e8, + 0x420ba361, + 0x420c25cb, + 0x420ca48b, + 0x420d24a5, + 0x420da4dc, + 0x421224f6, + 0x42172592, + 0x4217a538, + 0x421c255a, + 0x421f2515, + 0x422125e2, + 0x42262575, + 0x422b267b, + 0x422ba644, + 0x422c2663, + 0x422ca61e, + 0x422d25fd, 0x443206ad, 0x443286bc, 0x443306c8, @@ -1858,94 +1882,94 @@ 0x44390782, 0x44398790, 0x443a07a3, - 0x4c32124f, - 0x4c32925f, - 0x4c331272, - 0x4c339292, + 0x4c321278, + 0x4c329288, + 0x4c33129b, + 0x4c3392bb, 0x4c340094, 0x4c3480b0, - 0x4c35129e, - 0x4c3592ac, - 0x4c3612c8, - 0x4c3692db, - 0x4c3712ea, - 0x4c3792f8, - 0x4c38130d, - 0x4c389319, - 0x4c391339, - 0x4c399363, - 0x4c3a137c, - 0x4c3a9395, + 0x4c3512c7, + 0x4c3592d5, + 0x4c3612f1, + 0x4c369304, + 0x4c371313, + 0x4c379321, + 0x4c381336, + 0x4c389342, + 0x4c391362, + 0x4c39938c, + 0x4c3a13a5, + 0x4c3a93be, 0x4c3b05d0, - 0x4c3b93ae, - 0x4c3c13c0, - 0x4c3c93cf, - 0x4c3d105c, - 0x4c3d93e8, - 0x4c3e13f5, - 0x50322c47, - 0x5032ac56, - 0x50332c61, - 0x5033ac71, - 0x50342c8a, - 0x5034aca4, - 0x50352cb2, - 0x5035acc8, - 0x50362cda, - 0x5036acf0, - 0x50372d09, - 0x5037ad1c, - 0x50382d34, - 0x5038ad45, - 0x50392d5a, - 0x5039ad6e, - 0x503a2d8e, - 0x503aada4, - 0x503b2dbc, - 0x503badce, - 0x503c2dea, - 0x503cae01, - 0x503d2e1a, - 0x503dae30, - 0x503e2e3d, - 0x503eae53, - 0x503f2e65, + 0x4c3b93d7, + 0x4c3c13e9, + 0x4c3c93f8, + 0x4c3d1085, + 0x4c3d9411, + 0x4c3e141e, + 0x50322c91, + 0x5032aca0, + 0x50332cab, + 0x5033acbb, + 0x50342cd4, + 0x5034acee, + 0x50352cfc, + 0x5035ad12, + 0x50362d24, + 0x5036ad3a, + 0x50372d53, + 0x5037ad66, + 0x50382d7e, + 0x5038ad8f, + 0x50392da4, + 0x5039adb8, + 0x503a2dd8, + 0x503aadee, + 0x503b2e06, + 0x503bae18, + 0x503c2e34, + 0x503cae4b, + 0x503d2e64, + 0x503dae7a, + 0x503e2e87, + 0x503eae9d, + 0x503f2eaf, 0x503f8348, - 0x50402e78, - 0x5040ae88, - 0x50412ea2, - 0x5041aeb1, - 0x50422ecb, - 0x5042aee8, - 0x50432ef8, - 0x5043af08, - 0x50442f17, + 0x50402ec2, + 0x5040aed2, + 0x50412eec, + 0x5041aefb, + 0x50422f15, + 0x5042af32, + 0x50432f42, + 0x5043af52, + 0x50442f61, 0x50448414, - 0x50452f2b, - 0x5045af49, - 0x50462f5c, - 0x5046af72, - 0x50472f84, - 0x5047af99, - 0x50482fbf, - 0x5048afcd, - 0x50492fe0, - 0x5049aff5, - 0x504a300b, - 0x504ab01b, - 0x504b303b, - 0x504bb04e, - 0x504c3071, - 0x504cb09f, - 0x504d30b1, - 0x504db0ce, - 0x504e30e9, - 0x504eb105, - 0x504f3117, - 0x504fb12e, - 0x5050313d, + 0x50452f75, + 0x5045af93, + 0x50462fa6, + 0x5046afbc, + 0x50472fce, + 0x5047afe3, + 0x50483009, + 0x5048b017, + 0x5049302a, + 0x5049b03f, + 0x504a3055, + 0x504ab065, + 0x504b3085, + 0x504bb098, + 0x504c30bb, + 0x504cb0e9, + 0x504d30fb, + 0x504db118, + 0x504e3133, + 0x504eb14f, + 0x504f3161, + 0x504fb178, + 0x50503187, 0x50508687, - 0x50513150, + 0x5051319a, 0x58320de7, 0x68320da9, 0x68328b8e, @@ -1981,7 +2005,7 @@ 0x783d0a8e, 0x783d8aa3, 0x783e09f9, - 0x80321151, + 0x8032117a, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); @@ -2175,6 +2199,7 @@ "NOT_IMPLEMENTED\0" "RANDOM_NUMBER_GENERATION_FAILED\0" "OPERATION_NOT_SUPPORTED\0" + "BN_DECODE_ERROR\0" "COMMAND_NOT_SUPPORTED\0" "CONTEXT_NOT_INITIALISED\0" "DIFFERENT_KEY_TYPES\0" @@ -2204,6 +2229,7 @@ "NO_PARAMETERS_SET\0" "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0" "OPERATON_NOT_INITIALIZED\0" + "PARAMETER_ENCODING_ERROR\0" "UNKNOWN_DIGEST\0" "UNKNOWN_MASK_DIGEST\0" "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0" @@ -2385,6 +2411,7 @@ "NULL_SSL_CTX\0" "NULL_SSL_METHOD_PASSED\0" "OLD_SESSION_CIPHER_NOT_RETURNED\0" + "OLD_SESSION_VERSION_NOT_RETURNED\0" "PACKET_LENGTH_TOO_LONG\0" "PARSE_TLSEXT\0" "PATH_TOO_LONG\0"
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium index 0ebfeef9..32ff4e0 100644 --- a/third_party/libjingle/README.chromium +++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@ Name: libjingle URL: http://code.google.com/p/webrtc/ Version: unknown -Revision: 8930 +Revision: 8956 License: BSD License File: source/talk/COPYING Security Critical: yes
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py b/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py index c9961e7..cc42bd9 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py
@@ -124,6 +124,16 @@ return 'chrome_proxy_benchmark.lo_fi.lo_fi' +class ChromeProxyExpDirective(benchmark.Benchmark): + tag = 'exp_directive' + test = measurements.ChromeProxyExpDirective + page_set = pagesets.ExpDirectivePageSet + + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.exp_directive.exp_directive' + + class ChromeProxyBypass(benchmark.Benchmark): tag = 'bypass' test = measurements.ChromeProxyBypass
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py index ee756192..c39f162 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
@@ -310,6 +310,23 @@ def AddResults(self, tab, results): self._metrics.AddResultsForLoFi(tab, results) +class ChromeProxyExpDirective(ChromeProxyValidation): + """Correctness measurement for experiment directives in Chrome-Proxy header. + + This test verifies that "exp=test" in the Chrome-Proxy request header + causes a bypass on the experiment test page. + """ + + def __init__(self): + super(ChromeProxyExpDirective, self).__init__(restart_after_each_page=True) + + def CustomizeBrowserOptions(self, options): + super(ChromeProxyExpDirective, self).CustomizeBrowserOptions(options) + options.AppendExtraBrowserArgs('--data-reduction-proxy-experiment=test') + + def AddResults(self, tab, results): + self._metrics.AddResultsForBypass(tab, results) + class ChromeProxyHTTPToDirectFallback(ChromeProxyValidation): """Correctness measurement for HTTP proxy fallback to direct."""
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/exp_directive.py b/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/exp_directive.py new file mode 100644 index 0000000..49a274c --- /dev/null +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/exp_directive.py
@@ -0,0 +1,27 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from telemetry.page import page as page_module +from telemetry.page import page_set as page_set_module + + +class ExpDirectivePage(page_module.Page): + """A test page for the experiment Chrome-Proxy directive tests.""" + + def __init__(self, url, page_set): + super(ExpDirectivePage, self).__init__(url=url, page_set=page_set) + + +class ExpDirectivePageSet(page_set_module.PageSet): + """ Chrome proxy test sites """ + + def __init__(self): + super(ExpDirectivePageSet, self).__init__() + + urls_list = [ + 'http://aws1.mdw.la/exptest/', + ] + + for url in urls_list: + self.AddUserStory(ExpDirectivePage(url, self))
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp index 48d6a73..f219b34 100644 --- a/tools/clang/plugins/ChromeClassTester.cpp +++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -7,12 +7,14 @@ #include "ChromeClassTester.h" -#include <sys/param.h> - #include "clang/AST/AST.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" +#ifdef LLVM_ON_UNIX +#include <sys/param.h> +#endif + using namespace clang; namespace { @@ -258,6 +260,7 @@ return true; } +#ifdef LLVM_ON_UNIX // We need to munge the paths so that they are relative to the repository // srcroot. We first resolve the symlinktastic relative path and then // remove our known srcroot from it if needed. @@ -265,11 +268,11 @@ if (realpath(filename.c_str(), resolvedPath)) { filename = resolvedPath; } +#endif - for (size_t i = 0; i < banned_directories_.size(); ++i) { + for (const std::string& banned_dir : banned_directories_) { // If any of the banned directories occur as a component in filename, // this file is rejected. - const std::string& banned_dir = banned_directories_[i]; assert(banned_dir.front() == '/' && "Banned dir must start with '/'"); assert(banned_dir.back() == '/' && "Banned dir must end with '/'");
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index c77a4fb..17254c2 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -6,6 +6,7 @@ """Windows can't run .sh files, so this is a Python implementation of update.sh. This script should replace update.sh on all platforms eventually.""" +import argparse import os import re import shutil @@ -30,6 +31,7 @@ THIS_DIR = os.path.abspath(os.path.dirname(__file__)) CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..')) LLVM_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm') +CHROME_TOOLS_SHIM_DIR = os.path.join(LLVM_DIR, 'tools', 'chrometools') LLVM_BUILD_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build', 'Release+Asserts') COMPILER_RT_BUILD_DIR = os.path.join(LLVM_BUILD_DIR, '32bit-compiler-rt') @@ -129,6 +131,32 @@ RunCommand(command) +def DeleteChromeToolsShim(): + shutil.rmtree(CHROME_TOOLS_SHIM_DIR, ignore_errors=True) + + +def CreateChromeToolsShim(): + """Hooks the Chrome tools into the LLVM build. + + Several Chrome tools have dependencies on LLVM/Clang libraries. The LLVM build + detects implicit tools in the tools subdirectory, so this helper install a + shim CMakeLists.txt that forwards to the real directory for the Chrome tools. + + Note that the shim directory name intentionally has no - or _. The implicit + tool detection logic munges them in a weird way.""" + assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_') + os.mkdir(CHROME_TOOLS_SHIM_DIR) + with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f: + f.write('# Automatically generated by tools/clang/scripts/update.py. ' + + 'Do not edit.\n') + f.write('# Since tools/clang is located in another directory, use the \n') + f.write('# two arg version to specify where build artifacts go. CMake\n') + f.write('# disallows reuse of the same binary dir for multiple source\n') + f.write('# dirs, so the build artifacts need to go into a subdirectory.\n') + f.write('add_subdirectory(${CHROMIUM_TOOLS_SRC} ' + + '${CMAKE_CURRENT_BINARY_DIR}/a)\n') + + def AddCMakeToPath(): """Look for CMake and add it to PATH if it's not there already.""" try: @@ -181,30 +209,39 @@ return '' -def UpdateClang(): +def UpdateClang(args): print 'Updating Clang to %s...' % (LLVM_WIN_REVISION) if LLVM_WIN_REVISION != 'HEAD' and ReadStampFile() == LLVM_WIN_REVISION: print 'Already up to date.' return 0 AddCMakeToPath() - ClobberChromiumBuildFiles() + if args.clobber: + ClobberChromiumBuildFiles() # Reset the stamp file in case the build is unsuccessful. WriteStampFile('') + DeleteChromeToolsShim(); Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR) Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR) Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR) Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR) + CreateChromeToolsShim(); if not os.path.exists(LLVM_BUILD_DIR): os.makedirs(LLVM_BUILD_DIR) os.chdir(LLVM_BUILD_DIR) + cmake_args = ['-GNinja', '-DCMAKE_BUILD_TYPE=Release', + '-DLLVM_ENABLE_ASSERTIONS=ON', SubversionCmakeArg(), + '-DCHROMIUM_TOOLS_SRC=%s' % os.path.join( + CHROMIUM_DIR, 'tools', 'clang')] + if args.tools: + cmake_args.append('-DCHROMIUM_TOOLS=%s' % ';'.join(args.tools)) + RunCommand(GetVSVersion().SetupScript('x64') + - ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release', - '-DLLVM_ENABLE_ASSERTIONS=ON', SubversionCmakeArg(), LLVM_DIR]) + ['&&', 'cmake'] + cmake_args + [LLVM_DIR]) RunCommand(GetVSVersion().SetupScript('x64') + ['&&', 'ninja', 'all']) # Do an x86 build of compiler-rt to get the 32-bit ASan run-time. @@ -213,8 +250,7 @@ os.makedirs(COMPILER_RT_BUILD_DIR) os.chdir(COMPILER_RT_BUILD_DIR) RunCommand(GetVSVersion().SetupScript('x86') + - ['&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release', - '-DLLVM_ENABLE_ASSERTIONS=ON', LLVM_DIR]) + ['&&', 'cmake'] + cmake_args + [LLVM_DIR]) RunCommand(GetVSVersion().SetupScript('x86') + ['&&', 'ninja', 'compiler-rt']) # TODO(hans): Make this (and the .gypi and .isolate files) version number @@ -276,7 +312,13 @@ print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).' return 0 - return UpdateClang() + parser = argparse.ArgumentParser(description='Build Clang.') + parser.add_argument('--no-clobber', dest='clobber', action='store_false') + parser.add_argument('--tools', nargs='*') + # For now, this flag is only used for the non-Windows flow, but argparser gets + # mad if it sees a flag it doesn't recognize. + parser.add_argument('--if-needed', action='store_true') + return UpdateClang(parser.parse_args()) if __name__ == '__main__':
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh index 10a4645..32d2ead5 100755 --- a/tools/clang/scripts/update.sh +++ b/tools/clang/scripts/update.sh
@@ -190,14 +190,13 @@ fi fi - if [[ "${OS}" == "Linux" ]]; then - # TODO(hans): Might need to make this work on Mac eventually. + if [[ "${OS}" == "Linux" || "${OS}" == "Darwin" ]]; then if [[ $(cmake --version | grep -Eo '[0-9.]+') < "3.0" ]]; then # We need a newer CMake version. if [[ ! -e "${LLVM_BUILD_TOOLS_DIR}/cmake310" ]]; then echo "Downloading pre-built CMake 3.10..." mkdir -p "${LLVM_BUILD_TOOLS_DIR}" - curl --fail -L "${CDS_URL}/tools/cmake310.tgz" | \ + curl --fail -L "${CDS_URL}/tools/cmake310_${OS}.tgz" | \ tar zxf - -C "${LLVM_BUILD_TOOLS_DIR}" echo Done fi
diff --git a/tools/gn/misc/emacs/gn-mode.el b/tools/gn/misc/emacs/gn-mode.el index ebac11b8..c7ee08bc 100644 --- a/tools/gn/misc/emacs/gn-mode.el +++ b/tools/gn/misc/emacs/gn-mode.el
@@ -20,8 +20,6 @@ ;; - We syntax highlight builtin actions, but don't highlight instantiations of ;; templates. Should we? -;; - `fill-paragraph' works for comments, but when pointed at code, breaks -;; spectacularly. @@ -118,6 +116,14 @@ (and (not (smie-rule-bolp)) (smie-rule-prev-p "else") (smie-rule-parent))))) +(defun gn-fill-paragraph (&optional justify) + "We only fill inside of comments in GN mode." + (interactive "P") + (or (fill-comment-paragraph justify) + ;; Never return nil; `fill-paragraph' will perform its default behavior + ;; if we do. + t)) + ;;;###autoload (define-derived-mode gn-mode prog-mode "GN" "Major mode for editing gn (Generate Ninja)." @@ -127,6 +133,8 @@ (setq-local comment-start "#") (setq-local comment-end "") + (setq-local fill-paragraph-function 'gn-fill-paragraph) + (setq-local font-lock-defaults '(gn-font-lock-keywords)) ;; For every 'rule("name") {', adds "name" to the imenu for quick navigation.
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc index 43a6c76..0d39e2b 100644 --- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc +++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -1274,6 +1274,20 @@ } }; +template <> +struct FuzzTraits<HostID> { + static bool Fuzz(HostID* p, Fuzzer* fuzzer) { + HostID::HostType type = p->type(); + std::string id = p->id(); + if (!FuzzParam(&type, fuzzer)) + return false; + if (!FuzzParam(&id, fuzzer)) + return false; + *p = HostID(type, id); + return true; + } +}; + #if defined(OS_WIN) template <> struct FuzzTraits<HWND> {
diff --git a/tools/ipc_fuzzer/message_lib/all_messages.h b/tools/ipc_fuzzer/message_lib/all_messages.h index 1cd32166..f9430ad 100644 --- a/tools/ipc_fuzzer/message_lib/all_messages.h +++ b/tools/ipc_fuzzer/message_lib/all_messages.h
@@ -9,6 +9,7 @@ // Force all multi-include optional files to be included again. #undef CHROME_COMMON_COMMON_PARAM_TRAITS_MACROS_H_ #undef COMPONENTS_AUTOFILL_CONTENT_COMMON_AUTOFILL_PARAM_TRAITS_MACROS_H_ +#undef COMPONENTS_NACL_COMMON_NACL_TYPES_PARAM_TRAITS_H_ #undef CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_ #undef CONTENT_COMMON_FRAME_PARAM_MACROS_H_ #undef CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
diff --git a/tools/mb/README.md b/tools/mb/README.md new file mode 100644 index 0000000..beba946 --- /dev/null +++ b/tools/mb/README.md
@@ -0,0 +1,22 @@ +# MB - The Meta-Build wrapper + +MB is a simple wrapper intended to provide a uniform interface to either +GYP or GN, such that users and bots can call one script and not need to +worry about whether a given bot is meant to use GN or GYP. + +It supports two main functions: + +1. "gen" - the main `gyp_chromium` / `gn gen` invocation that generates the + Ninja files needed for the build. + +2. "analyze" - the step that takes a list of modified files and a list of + desired targets and reports which targets will need to be rebuilt. + +We also use MB as a forcing function to collect all of the different +build configurations that we actually support for Chromium builds into +one place, in `//tools/mb/mb_config.pyl`. + +For more information, see: + +* [the user guide](docs/user_guide.md) +* [the design spec](docs/design_spec.md)
diff --git a/tools/mb/docs/design_spec.md b/tools/mb/docs/design_spec.md new file mode 100644 index 0000000..5673fae --- /dev/null +++ b/tools/mb/docs/design_spec.md
@@ -0,0 +1,156 @@ +# The MB (Meta-Build wrapper) design spec + +[TOC] + +## Intro + +MB is intended to address two major aspects of the GYP -> GN transition +for Chromium: + +1. "bot toggling" - make it so that we can easily flip a given bot + back and forth between GN and GYP. + +2. "bot configuration" - provide a single source of truth for all of + the different configurations (os/arch/`gyp_define` combinations) of + Chromium that are supported. + +MB must handle at least the `gen` and `analyze` steps on the bots, i.e., +we need to wrap both the `gyp_chromium` invocation to generate the +Ninja files, and the `analyze` step that takes a list of modified files +and a list of targets to build and returns which targets are affected by +the files. + +## Design + +MB is intended to be as simple as possible, and to defer as much work as +possible to GN or GYP. It should live as a very simple Python wrapper +that offers little in the way of surprises. + +### Command line + +It is structured as a single binary that supports a list of subcommands: + +* `mb gen -c linux_rel_bot //out/Release` +* `mb analyze -m tryserver.chromium.linux -b linux_rel /tmp/input.json /tmp/output.json` + +### Configurations + +`mb` looks in the `//tools/mb/mb_config.pyl` config file to determine whether +to use GYP or GN for a particular build directory, and what set of flags +(`GYP_DEFINES` or `gn args`) to use. + +A config can either be specified directly (useful for testing) or by specifying +the master name and builder name (useful on the bots so that they do not need +to specify a config directly and can be hidden from the details). + +See the [user guide](user_guide.md#mb_config.pyl) for details. + +### Handling the analyze step + +The interface to `mb analyze` is described in the +[user\_guide](user_guide.md#mb_analyze). + +Since the interface basically mirrors the way the "analyze" step on the bots +invokes gyp\_chromium today, when the config is found to be a gyp config, +the arguments are passed straight through. + +It implements the equivalent functionality in GN by calling `'gn refs +[list of files] --type=executable --all --as=output` and filtering the +output to match the list of targets. + +## Detailed Design Requirements and Rationale + +This section is collection of semi-organized notes on why MB is the way +it is ... + +### in-tree or out-of-tree + +The first issue is whether or not this should exist as a script in +Chromium at all; an alternative would be to simply change the bot +configurations to know whether to use GYP or GN, and which flags to +pass. + +That would certainly work, but experience over the past two years +suggests a few things: + + * we should push as much logic as we can into the source repositories + so that they can be versioned and changed atomically with changes to + the product code; having to coordinate changes between src/ and + build/ is at best annoying and can lead to weird errors. + * the infra team would really like to move to providing + product-independent services (i.e., not have to do one thing for + Chromium, another for NaCl, a third for V8, etc.). + * we found that during the SVN->GIT migration the ability to flip bot + configurations between the two via changes to a file in chromium + was very useful. + +All of this suggests that the interface between bots and Chromium should +be a simple one, hiding as much of the chromium logic as possible. + +### Why not have MB be smarter about de-duping flags? + +This just adds complexity to the MB implementation, and duplicates logic +that GYP and GN already have to support anyway; in particular, it might +require MB to know how to parse GYP and GN values. The belief is that +if MB does *not* do this, it will lead to fewer surprises. + +It will not be hard to change this if need be. + +### Integration w/ gclient runhooks + +On the bots, we will disable `gyp_chromium` as part of runhooks (using +`GYP_CHROMIUM_NO_ACTION=1`), so that mb shows up as a separate step. + +At the moment, we expect most developers to either continue to use +`gyp_chromium` in runhooks or to disable at as above if they have no +use for GYP at all. We may revisit how this works once we encourage more +people to use GN full-time (i.e., we might take `gyp_chromium` out of +runhooks altogether). + +### Config per flag set or config per (os/arch/flag set)? + +Currently, mb_config.pyl does not specify the host_os, target_os, host_cpu, or +target_cpu values for every config that Chromium runs on, it only specifies +them for when the values need to be explicitly set on the command line. + +Instead, we have one config per unique combination of flags only. + +In other words, rather than having `linux_rel_bot`, `win_rel_bot`, and +`mac_rel_bot`, we just have `rel_bot`. + +This design allows us to determine easily all of the different sets +of flags that we need to support, but *not* which flags are used on which +host/target combinations. + +It may be that we should really track the latter. Doing so is just a +config file change, however. + +### Non-goals + +* MB is not intended to replace direct invocation of GN or GYP for + complicated build scenarios (aka ChromeOS), where multiple flags need + to be set to user-defined paths for specific toolchains (e.g., where + ChromeOS needs to specify specific board types and compilers). + +* MB is not intended at this time to be something developers use frequently, + or to add a lot of features to. We hope to be able to get rid of it once + the GYP->GN migration is done, and so we should not add things for + developers that can't easily be added to GN itself. + +* MB is not intended to replace the + [CR tool](https://code.google.com/p/chromium/wiki/CRUserManual). Not + only is it only intended to replace the gyp\_chromium part of `'gclient + runhooks'`, it is not really meant as a developer-facing tool. + +### Open issues + +* Some common flags (goma\_dir being the obvious one) may need to be + specified via the user, and it's unclear how to integrate this with + the concept of build\_configs. + + Right now, MB has hard-coded support for a few flags (i.e., you can + pass the --goma-dir flag, and it will know to expand "${goma\_dir}" in + the string before calling out to the tool. We may want to generalize + this to a common key/value approach (perhaps then meeting the + ChromeOS non-goal, above), or we may want to keep this very strictly + limited for simplicity.
diff --git a/tools/mb/docs/user_guide.md b/tools/mb/docs/user_guide.md new file mode 100644 index 0000000..8aff68d --- /dev/null +++ b/tools/mb/docs/user_guide.md
@@ -0,0 +1,195 @@ +# The MB (Meta-Build wrapper) user guide + +[TOC] + +## Introduction + +`mb` is a simple python wrapper around the GYP and GN meta-build tools to +be used as part of the GYP->GN migration. + +It is intended to be used by bots to make it easier to manage the configuration +each bot builds (i.e., the configurations can be changed from chromium +commits), and to consolidate the list of all of the various configurations +that Chromium is built in. + +Ideally this tool will no longer be needed after the migration is complete. + +## `mb gen` + +`mb gen` is responsible for generating the Ninja files by invoking either GYP +or GN as appropriate. It takes arguments to specify a build config and +a directory, then runs GYP or GN as appropriate: + +``` +% mb gen -m tryserver.chromium.linux -b linux_rel //out/Release +% mb gen -c linux_rel_trybot //out/Release +``` + +Either the `-c/--config` flag or the `-m/--master` and `-b/--builder` flags +must be specified so that `mb` can figure out which config to use. + +The path must be a GN-style "source-absolute" path (as above). + +If gen ends up using GYP, the path must have a valid GYP configuration as the +last component of the path (i.e., specify `//out/Release_x64`, not `//out`). + +## `mb analyze` + +`mb analyze` is reponsible for determining what targets are affected by +a list of files (e.g., the list of files in a patch on a trybot): + +``` +mb analyze -c chromium_linux_rel //out/Release input.json output.json +``` + +Either the `-c/--config` flag or the `-m/--master` and `-b/--builder` flags +must be specified so that `mb` can figure out which config to use. + + +The first positional argument must be a GN-style "source-absolute" path +to the build directory. + +The second positional argument is a (normal) path to a JSON file containing +a single object with two fields: + + * `files`: an array of the modified filenames to check (as + paths relative to the checkout root). + * `targets`: an array of the unqualified target names to check. + +The third positional argument is a (normal) path to where mb will write +the result, also as a JSON object. This object may contain the following +fields: + + * `error`: this should only be present if something failed. + * `targets`: the subset of the input `targets` that depend on the + input `files`. + * `build_targets`: the minimal subset of targets needed to build all + of `targets` that were affected. + * `status`: one of three strings: + * `"Found dependency"` (build the `build_targets`) + * `"No dependency"` (i.e., no build needed) + * `"Found dependency (all)"` (build everything, in which case + `targets` and `build_targets` are not returned). + +## `mb help` + +Produces help output on the other subcommands + +## `mb lookup` + +Prints what command will be run by `mb gen` (like `mb gen -n` but does +not require you to specify a path). + +## `mb validate` + +Does internal checking to make sure the config file is syntactically +valid and that all of the entries are used properly. It does not validate +that the flags make sense, or that the builder names are legal or +comprehensive, but it does complain about configs and mixins that aren't +used. + +This is mostly useful as a presubmit check and for verifying changes to +the config file. + +## mb_config.pyl + +The `mb_config.pyl` config file is intended to enumerate all of the +supported build configurations for Chromium. Generally speaking, you +should never need to (or want to) build a configuration that isn't +listed here, and so by using the configs in this file you can avoid +having to juggle long lists of GYP_DEFINES and gn args by hand. + +`mb_config.pyl` is structured as a file containing a single PYthon Literal +expression: a dictionary with three main keys, `masters`, `configs` and +`mixins`. + +The `masters` key contains a nested series of dicts containing mappings +of master -> builder -> config . This allows us to isolate the buildbot +recipes from the actual details of the configs. + +The `configs` key points to a dictionary of named build +configurations. + +There should be an key in this dict for every supported configuration +of Chromium, meaning every configuration we have a bot for, and every +configuration commonly used by develpers but that we may not have a bot +for. + +The value of each key is a list of "mixins" that will define what that +build_config does. Each item in the list must be an entry in the dictionary +value of the `mixins` key. + +Each mixin value is itself a dictionary that contains one or more of the +following keys: + + * `gyp_configs`: a list of the configurations to build, e.g., + ['Release', 'Release_x64']. + * `gyp_defines`: a string containing a list of GYP_DEFINES. + * `gn_args`: a string containing a list of values passed to gn --args. + * `mixins`: a list of other mixins that should be included. + * `type`: a string with either the value `gyp` or `gn`; + setting this indicates which meta-build tool to use. + +When `mb gen` or `mb analyze` executes, it takes a config name, looks it +up in the 'configs' dict, and then does a left-to-right expansion of the +mixins; gyp_defines and gn_args values are concatenated, and type and +gyp_configs values override each other. + +For example, if you had: + +``` +{ + 'configs`: { + 'linux_release_trybot': ['gyp_release', 'trybot'], + 'gn_shared_debug': None, + } + 'mixins': { + 'bot': { + 'gyp_defines': 'use_goma=1 dcheck_always_on=0', + 'gn_args': 'use_goma=true dcheck_always_on=false', + }, + 'debug': { + 'gn_args': 'is_debug=true', + }, + 'gn': {'type': 'gn'}, + 'gyp_release': { + 'gyp_config': 'Release' + 'mixins': ['release'], + 'type': 'gyp', + }, + 'release': { + 'gn_args': 'is_debug=false', + } + 'shared': { + 'gn_args': 'is_component_build=true', + 'gyp_defines': 'component=shared_library', + }, + 'trybot': { + 'gyp_defines': 'dcheck_always_on=1', + 'gn_args': 'dcheck_always_on=true', + } + } +} + +and you ran `mb gen -c linux_release_trybot //out/Release`, it would +translate into a call to `gyp_chromium -G Release` with `GYP_DEFINES` set to +`"use_goma=true dcheck_always_on=false dcheck_always_on=true"`. + +(From that you can see that mb is intentionally dumb and does not +attempt to de-dup the flags, it lets gyp do that). + +## Debugging (-v/--verbose and -n/--dry-run) + +By design, MB should be simple enough that very little can go wrong. + +The most obvious issue is that you might see different commands being +run than you expect; running `'mb -v'` will print what it's doing and +run the commands; `'mb -n'` will print what it will do but *not* run +the commands. + +If you hit weirder things than that, add some print statements to the +python script, send a question to gn-dev@chromium.org, or +[file a bug](https://crbug.com/new) with the label +'mb' and cc: dpranke@chromium.org. + +
diff --git a/tools/mb/mb b/tools/mb/mb new file mode 100755 index 0000000..d3a0cdf0 --- /dev/null +++ b/tools/mb/mb
@@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +base_dir=$(dirname "$0") + +PYTHONDONTWRITEBYTECODE=1 exec python "$base_dir/mb.py" "$@"
diff --git a/tools/mb/mb.bat b/tools/mb/mb.bat new file mode 100755 index 0000000..a82770e7 --- /dev/null +++ b/tools/mb/mb.bat
@@ -0,0 +1,6 @@ +@echo off +setlocal +:: This is required with cygwin only. +PATH=%~dp0;%PATH% +set PYTHONDONTWRITEBYTECODE=1 +call python "%~dp0mb.py" %*
diff --git a/tools/mb/mb.py b/tools/mb/mb.py new file mode 100755 index 0000000..d18045c --- /dev/null +++ b/tools/mb/mb.py
@@ -0,0 +1,510 @@ +#!/usr/bin/env python +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""MB - the Meta-Build wrapper around GYP and GN + +MB is a wrapper script for GYP and GN that can be used to generate build files +for sets of canned configurations and analyze them. +""" + +from __future__ import print_function + +import argparse +import ast +import json +import os +import pipes +import shlex +import shutil +import sys +import subprocess + + +def main(args): + mbw = MetaBuildWrapper() + mbw.ParseArgs(args) + return mbw.args.func() + + +class MetaBuildWrapper(object): + def __init__(self): + p = os.path + d = os.path.dirname + self.chromium_src_dir = p.normpath(d(d(d(p.abspath(__file__))))) + self.default_config = p.join(self.chromium_src_dir, 'tools', 'mb', + 'mb_config.pyl') + self.args = argparse.Namespace() + self.configs = {} + self.masters = {} + self.mixins = {} + self.private_configs = [] + self.common_dev_configs = [] + self.unsupported_configs = [] + + def ParseArgs(self, argv): + def AddCommonOptions(subp): + subp.add_argument('-b', '--builder', + help='builder name to look up config from') + subp.add_argument('-m', '--master', + help='master name to look up config from') + subp.add_argument('-c', '--config', + help='configuration to analyze') + subp.add_argument('-f', '--config-file', metavar='PATH', + default=self.default_config, + help='path to config file ' + '(default is //tools/mb/mb_config.pyl)') + subp.add_argument('-g', '--goma-dir', default=self.ExpandUser('~/goma'), + help='path to goma directory (default is %(default)s).') + subp.add_argument('-n', '--dryrun', action='store_true', + help='Do a dry run (i.e., do nothing, just print ' + 'the commands that will run)') + subp.add_argument('-q', '--quiet', action='store_true', + help='Do not print anything, just return an exit ' + 'code.') + subp.add_argument('-v', '--verbose', action='count', + help='verbose logging (may specify multiple times).') + + parser = argparse.ArgumentParser(prog='mb') + subps = parser.add_subparsers() + + subp = subps.add_parser('analyze', + help='analyze whether changes to a set of files ' + 'will cause a set of binaries to be rebuilt.') + AddCommonOptions(subp) + subp.add_argument('path', type=str, nargs=1, + help='path build was generated into.') + subp.add_argument('input_path', nargs=1, + help='path to a file containing the input arguments ' + 'as a JSON object.') + subp.add_argument('output_path', nargs=1, + help='path to a file containing the output arguments ' + 'as a JSON object.') + subp.set_defaults(func=self.CmdAnalyze) + + subp = subps.add_parser('gen', + help='generate a new set of build files') + AddCommonOptions(subp) + subp.add_argument('path', type=str, nargs=1, + help='path to generate build into') + subp.set_defaults(func=self.CmdGen) + + subp = subps.add_parser('lookup', + help='look up the command for a given config or ' + 'builder') + AddCommonOptions(subp) + subp.set_defaults(func=self.CmdLookup) + + subp = subps.add_parser('validate', + help='validate the config file') + AddCommonOptions(subp) + subp.set_defaults(func=self.CmdValidate) + + subp = subps.add_parser('help', + help='Get help on a subcommand.') + subp.add_argument(nargs='?', action='store', dest='subcommand', + help='The command to get help for.') + subp.set_defaults(func=self.CmdHelp) + + self.args = parser.parse_args(argv) + + def CmdAnalyze(self): + vals = self.GetConfig() + if vals['type'] == 'gn': + return self.RunGNAnalyze(vals) + elif vals['type'] == 'gyp': + return self.RunGYPAnalyze(vals) + else: + raise MBErr('Unknown meta-build type "%s"' % vals['type']) + + def CmdGen(self): + vals = self.GetConfig() + if vals['type'] == 'gn': + self.RunGNGen(self.args.path[0], vals) + elif vals['type'] == 'gyp': + self.RunGYPGen(self.args.path[0], vals) + else: + raise MBErr('Unknown meta-build type "%s"' % vals['type']) + return 0 + + def CmdLookup(self): + vals = self.GetConfig() + if vals['type'] == 'gn': + cmd = self.GNCmd('<path>', vals['gn_args']) + elif vals['type'] == 'gyp': + cmd = self.GYPCmd('<path>', vals['gyp_defines'], vals['gyp_config']) + else: + raise MBErr('Unknown meta-build type "%s"' % vals['type']) + + self.PrintCmd(cmd) + return 0 + + def CmdHelp(self): + if self.args.subcommand: + self.ParseArgs([self.args.subcommand, '--help']) + else: + self.ParseArgs(['--help']) + + def CmdValidate(self): + errs = [] + + # Read the file to make sure it parses. + self.ReadConfigFile() + + # Figure out the whole list of configs and ensure that no config is + # listed in more than one category. + all_configs = {} + for config in self.common_dev_configs: + all_configs[config] = 'common_dev_configs' + for config in self.private_configs: + if config in all_configs: + errs.append('config "%s" listed in "private_configs" also ' + 'listed in "%s"' % (config, all_configs['config'])) + else: + all_configs[config] = 'private_configs' + for config in self.unsupported_configs: + if config in all_configs: + errs.append('config "%s" listed in "unsupported_configs" also ' + 'listed in "%s"' % (config, all_configs['config'])) + else: + all_configs[config] = 'unsupported_configs' + + for master in self.masters: + for builder in self.masters[master]: + config = self.masters[master][builder] + if config in all_configs and all_configs[config] not in self.masters: + errs.append('Config "%s" used by a bot is also listed in "%s".' % + (config, all_configs[config])) + else: + all_configs[config] = master + + # Check that every referenced config actually exists. + for config, loc in all_configs.items(): + if not config in self.configs: + errs.append('Unknown config "%s" referenced from "%s".' % + (config, loc)) + + # Check that every actual config is actually referenced. + for config in self.configs: + if not config in all_configs: + errs.append('Unused config "%s".' % config) + + # Figure out the whole list of mixins, and check that every mixin + # listed by a config or another mixin actually exists. + referenced_mixins = set() + for config, mixins in self.configs.items(): + for mixin in mixins: + if not mixin in self.mixins: + errs.append('Unknown mixin "%s" referenced by config "%s".' % + (mixin, config)) + referenced_mixins.add(mixin) + + for mixin in self.mixins: + for sub_mixin in self.mixins[mixin].get('mixins', []): + if not sub_mixin in self.mixins: + errs.append('Unknown mixin "%s" referenced by mixin "%s".' % + (sub_mixin, mixin)) + referenced_mixins.add(sub_mixin) + + # Check that every mixin defined is actually referenced somewhere. + for mixin in self.mixins: + if not mixin in referenced_mixins: + errs.append('Unreferenced mixin "%s".' % mixin) + + if errs: + raise MBErr('mb config file %s has problems:\n ' + '\n '.join(errs)) + + if not self.args.quiet: + self.Print('mb config file %s looks ok.' % self.args.config_file) + return 0 + + def GetConfig(self): + self.ReadConfigFile() + config = self.ConfigFromArgs() + if not config in self.configs: + raise MBErr('Config "%s" not found in %s' % + (config, self.args.config_file)) + + return self.FlattenConfig(config) + + def ReadConfigFile(self): + if not self.Exists(self.args.config_file): + raise MBErr('config file not found at %s' % self.args.config_file) + + try: + contents = ast.literal_eval(self.ReadFile(self.args.config_file)) + except SyntaxError as e: + raise MBErr('Failed to parse config file "%s": %s' % + (self.args.config_file, e)) + + self.common_dev_configs = contents['common_dev_configs'] + self.configs = contents['configs'] + self.masters = contents['masters'] + self.mixins = contents['mixins'] + self.private_configs = contents['private_configs'] + self.unsupported_configs = contents['unsupported_configs'] + + def ConfigFromArgs(self): + if self.args.config: + if self.args.master or self.args.builder: + raise MBErr('Can not specific both -c/--config and -m/--master or ' + '-b/--builder') + + return self.args.config + + if not self.args.master or not self.args.builder: + raise MBErr('Must specify either -c/--config or ' + '(-m/--master and -b/--builder)') + + if not self.args.master in self.masters: + raise MBErr('Master name "%s" not found in "%s"' % + (self.args.master, self.args.config_file)) + + if not self.args.builder in self.masters[self.args.master]: + raise MBErr('Builder name "%s" not found under masters[%s] in "%s"' % + (self.args.builder, self.args.master, self.args.config_file)) + + return self.masters[self.args.master][self.args.builder] + + def FlattenConfig(self, config): + mixins = self.configs[config] + vals = { + 'type': None, + 'gn_args': [], + 'gyp_config': [], + 'gyp_defines': [], + } + + visited = [] + self.FlattenMixins(mixins, vals, visited) + return vals + + def FlattenMixins(self, mixins, vals, visited): + for m in mixins: + if m not in self.mixins: + raise MBErr('Unknown mixin "%s"' % m) + + # TODO: check for cycles in mixins. + + visited.append(m) + + mixin_vals = self.mixins[m] + if 'type' in mixin_vals: + vals['type'] = mixin_vals['type'] + if 'gn_args' in mixin_vals: + if vals['gn_args']: + vals['gn_args'] += ' ' + mixin_vals['gn_args'] + else: + vals['gn_args'] = mixin_vals['gn_args'] + if 'gyp_config' in mixin_vals: + vals['gyp_config'] = mixin_vals['gyp_config'] + if 'gyp_defines' in mixin_vals: + if vals['gyp_defines']: + vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines'] + else: + vals['gyp_defines'] = mixin_vals['gyp_defines'] + if 'mixins' in mixin_vals: + self.FlattenMixins(mixin_vals['mixins'], vals, visited) + return vals + + def RunGNGen(self, path, vals): + cmd = self.GNCmd(path, vals['gn_args']) + ret, _, _ = self.Run(cmd) + return ret + + def GNCmd(self, path, gn_args): + # TODO(dpranke): Find gn explicitly in the path ... + cmd = ['gn', 'gen', path] + gn_args = gn_args.replace("$(goma_dir)", self.args.goma_dir) + if gn_args: + cmd.append('--args=%s' % gn_args) + return cmd + + def RunGYPGen(self, path, vals): + output_dir, gyp_config = self.ParseGYPConfigPath(path) + if gyp_config != vals['gyp_config']: + raise MBErr('The last component of the path (%s) must match the ' + 'GYP configuration specified in the config (%s), and ' + 'it does not.' % (gyp_config, vals['gyp_config'])) + cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) + ret, _, _ = self.Run(cmd) + return ret + + def RunGYPAnalyze(self, vals): + output_dir, gyp_config = self.ParseGYPConfigPath(self.args.path[0]) + if gyp_config != vals['gyp_config']: + raise MBErr('The last component of the path (%s) must match the ' + 'GYP configuration specified in the config (%s), and ' + 'it does not.' % (gyp_config, vals['gyp_config'])) + cmd = self.GYPCmd(output_dir, vals['gyp_defines'], config=gyp_config) + cmd.extend(['-G', 'config_path=%s' % self.args.input_path[0], + '-G', 'analyzer_output_path=%s' % self.args.output_path[0]]) + ret, _, _ = self.Run(cmd) + return ret + + def ToSrcRelPath(self, path): + """Returns a relative path from the top of the repo.""" + # TODO: Support normal paths in addition to source-absolute paths. + assert(path.startswith('//')) + return path[2:] + + def ParseGYPConfigPath(self, path): + rpath = self.ToSrcRelPath(path) + output_dir, _, config = rpath.rpartition('/') + self.CheckGYPConfigIsSupported(config, path) + return output_dir, config + + def CheckGYPConfigIsSupported(self, config, path): + if config not in ('Debug', 'Release'): + if (sys.platform in ('win32', 'cygwin') and + config not in ('Debug_x64', 'Release_x64')): + raise MBErr('Unknown or unsupported config type "%s" in "%s"' % + config, path) + + def GYPCmd(self, output_dir, gyp_defines, config): + gyp_defines = gyp_defines.replace("$(goma_dir)", self.args.goma_dir) + cmd = [ + sys.executable, + os.path.join('build', 'gyp_chromium'), + '-G', + 'output_dir=' + output_dir, + '-G', + 'config=' + config, + ] + for d in shlex.split(gyp_defines): + cmd += ['-D', d] + return cmd + + def RunGNAnalyze(self, _vals): + inp = self.GetAnalyzeInput() + + # Bail out early if a GN file was modified, since 'gn refs' won't know + # what to do about it. + if any(f.endswith('.gn') or f.endswith('.gni') for f in inp['files']): + self.WriteJSONOutput({'status': 'Found dependency (all)'}) + return 0 + + # TODO: Break long lists of files that might exceed the max command line + # up into chunks so that we can return more accurate info. + if len(' '.join(inp['files'])) > 1024: + self.WriteJSONOutput({'status': 'Found dependency (all)'}) + return 0 + + cmd = (['gn', 'refs', self.args.path[0] ] + + ['//' + f for f in inp['files']] + + ['--type=executable', '--all', '--as=output']) + needed_targets = [] + ret, out, _ = self.Run(cmd) + if ret: + self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out)) + + rpath = self.ToSrcRelPath(self.args.path[0]) + os.sep + needed_targets = [t.replace(rpath, '') for t in out.splitlines()] + needed_targets = [nt for nt in needed_targets if nt in inp['targets']] + + if needed_targets: + # TODO: it could be that a target X might depend on a target Y + # and both would be listed in the input, but we would only need + # to specify target X as a build_target (whereas both X and Y are + # targets). I'm not sure if that optimization is generally worth it. + self.WriteJSON({'targets': needed_targets, + 'build_targets': needed_targets, + 'status': 'Found dependency'}) + else: + self.WriteJSON({'targets': [], + 'build_targets': [], + 'status': 'No dependency'}) + + return 0 + + def GetAnalyzeInput(self): + path = self.args.input_path[0] + if not self.Exists(path): + self.WriteFailureAndRaise('"%s" does not exist' % path) + + try: + inp = json.loads(self.ReadFile(path)) + except Exception as e: + self.WriteFailureAndRaise('Failed to read JSON input from "%s": %s' % + (path, e)) + if not 'files' in inp: + self.WriteFailureAndRaise('input file is missing a "files" key') + if not 'targets' in inp: + self.WriteFailureAndRaise('input file is missing a "targets" key') + + return inp + + def WriteFailureAndRaise(self, msg): + self.WriteJSON({'error': msg}) + raise MBErr(msg) + + def WriteJSON(self, obj): + output_path = self.args.output_path[0] + if output_path: + try: + self.WriteFile(output_path, json.dumps(obj, indent=2) + '\n') + except Exception as e: + raise MBErr('Error %s writing to the output path "%s"' % + (e, output_path)) + + def PrintCmd(self, cmd): + if cmd[0] == sys.executable: + cmd = ['python'] + cmd[1:] + self.Print(*[pipes.quote(c) for c in cmd]) + + def Print(self, *args, **kwargs): + # This function largely exists so it can be overridden for testing. + print(*args, **kwargs) + + def Run(self, cmd): + # This function largely exists so it can be overridden for testing. + if self.args.dryrun or self.args.verbose: + self.PrintCmd(cmd) + if self.args.dryrun: + return 0, '', '' + ret, out, err = self.Call(cmd) + if self.args.verbose: + if out: + self.Print(out, end='') + if err: + self.Print(err, end='', file=sys.stderr) + return ret, out, err + + def Call(self, cmd): + p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + return p.returncode, out, err + + def ExpandUser(self, path): + # This function largely exists so it can be overridden for testing. + return os.path.expanduser(path) + + def Exists(self, path): + # This function largely exists so it can be overridden for testing. + return os.path.exists(path) + + def ReadFile(self, path): + # This function largely exists so it can be overriden for testing. + with open(path) as fp: + return fp.read() + + def WriteFile(self, path, contents): + # This function largely exists so it can be overriden for testing. + with open(path, 'w') as fp: + return fp.write(contents) + +class MBErr(Exception): + pass + + +if __name__ == '__main__': + try: + sys.exit(main(sys.argv[1:])) + except MBErr as e: + print(e) + sys.exit(1) + except KeyboardInterrupt: + print("interrupted, exiting", stream=sys.stderr) + sys.exit(130)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl new file mode 100644 index 0000000..6f26aed6 --- /dev/null +++ b/tools/mb/mb_config.pyl
@@ -0,0 +1,170 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + # This is the list of configs that you can pass to mb; each config + # represents a particular combination of GYP_DEFINES/gn args that + # we must support. A given config *may* be platform-specific but + # is not necessarily so (i.e., we might have mac, win, and linux + # bots all using the 'gn_release_bot' config). + 'configs': { + 'android_gn_release_bot': ['android', 'gn', 'release_bot'], + 'android_gn_debug_bot': ['android', 'gn', 'debug_bot'], + 'android_gn_release_trybot': ['android', 'gn', 'release_trybot'], + 'chromeos_gn_debug_bot': ['chromeos', 'gn', 'debug_bot'], + 'chromeos_gn_release_bot': ['chromeos', 'gn', 'release_bot'], + 'chromeos_gn_release_trybot': ['chromeos', 'gn', 'release_trybot'], + 'dev_gn_debug': ['gn', 'debug', 'shared', 'full_symbols'], + 'dev_gyp_debug': ['gyp', 'debug', 'shared', 'full_symbols'], + 'dev_gn_release': ['gn', 'release', 'shared'], + 'dev_gyp_release': ['gyp', 'release', 'shared'], + 'gn_release_bot': ['gn', 'release_bot'], + 'gn_release_bot_x86': ['gn', 'release_bot', 'x86'], + 'gn_release_trybot': ['gn', 'release_trybot'], + 'gn_debug_bot': ['gn', 'debug_bot'], + 'gyp_release_bot': ['gyp', 'release_bot'], + }, + + # This is a list of configs that do not actually exist on any bot + # but are used so commonly by devs that we must support them. + 'common_dev_configs': [ + 'dev_gn_debug', + 'dev_gn_release', + 'dev_gyp_debug', + 'dev_gyp_release', + ], + + # This is a list of configs that some private (not publicly accessible) + # bot somewhere uses and that we must support. Ideally we should actually + # have a bot for each of these on the public waterfall. Each config should + # at least have a contact listed. + 'private_configs': [ + ], + + # This is a list of configs that are not commonly used by that we should + # make some effort to support, but if it breaks that is not the end of + # the world. Each config should have a contact listed, and we expect the + # contact to be on the hook for fixing the config. + 'unsupported_configs': [ + ], + + # This is a dict mapping a given 'mixin' name to a dict of settings that + # mb should use. See //tools/mb/docs/user_guide.md for more information. + 'mixins': { + 'android': { + 'gn_args': 'target_os="android"', + 'gyp_defines': 'OS=android', + }, + + 'chromeos': { + 'gn_args': 'target_os="chromeos"', + 'gyp_defines': 'chromeos=1', + }, + + 'dcheck_always_on': { + 'gn_args': 'dcheck_always_on=true', + 'gyp_defines': 'dcheck_always_on=1', + }, + + 'debug': { + 'gn_args': 'is_debug=true', + 'gyp_config': 'Debug', + }, + + 'debug_bot': {'mixins': ['debug', 'shared', 'minimal_symbols', 'goma']}, + + 'full_symbols': { + 'gn_args': 'symbol_level=2', + 'gyp_defines': 'fastbuild=0', + }, + + 'gn': {'type': 'gn'}, + + 'goma': { + 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"', + 'gyp_defines': 'goma=1 gomadir=$(goma_dir)', + }, + + 'gyp': {'type': 'gyp'}, + + 'minimal_symbols': { + 'gn_args': 'symbol_level=1', + 'gyp_defines': 'fastbuild=1', + }, + + 'release': { + 'gn_args': 'is_debug=false', + 'gyp_config': 'Release', + }, + + 'release_bot': { + 'mixins': ['release', 'static', 'minimal_symbols', 'goma'], + }, + + 'release_trybot': { + 'mixins': ['release_bot', 'dcheck_always_on'] + }, + + 'shared': { + 'gn_args': 'is_component_build=true', + 'gyp_defines': 'component=shared_library', + }, + + 'static': { + 'gn_args': 'is_component_build=false', + 'gyp_defines': 'component=static_library', + }, + + 'x86': { + 'gn_args': 'target_cpu="x86"', + 'gyp_args': 'target_arch=ia32', + }, + }, + + + # This is a map of buildbot master names -> buildbot builder names -> + # config names (where each config name is a key in the 'configs' dict, + # above). mb uses this dict to look up which config to use for a given bot. + # TODO(dpranke): add in remaining bots on the waterfalls. + 'masters': { + 'chromium.chromeos': { + 'Linux ChromiumOS GN': 'chromeos_gn_release_bot', + }, + 'chromium.linux': { + 'Android GN': 'android_gn_release_bot', + 'Linux Builder': 'gyp_release_bot', + 'Linux GN': 'gn_release_bot', + 'Linux GN (dbg)': 'gn_debug_bot', + 'Linux Tests': 'gyp_release_bot', + }, + 'chromium.mac': { + 'Mac GN': 'gn_release_bot', + 'Mac GN (dbg)': 'gn_debug_bot', + }, + 'chromium.win': { + 'Win8 GN': 'gn_release_bot', + 'Win8 GN (dbg)': 'gn_debug_bot', + }, + 'tryserver.chromium.linux': { + 'android_chromium_gn_dbg': 'android_gn_debug_bot', + 'android_chromium_gn_rel': 'android_gn_release_trybot', + 'linux_chromiumos_chromium_gn_rel': 'chromeos_gn_release_trybot', + 'linux_chromiumos_chromium_gn_dbg': 'chromeos_gn_debug_bot', + 'linux_chromium_gn_dbg': 'gn_debug_bot', + 'linux_chromium_gn_rel': 'gn_release_trybot', + 'linux_chromium_gn_upload_x64': 'gn_release_bot', + 'linux_chromium_gn_upload_x86': 'gn_release_bot_x86', + }, + 'tryserver.chromium.mac': { + 'mac_chromium_gn_dbg': 'gn_debug_bot', + 'mac_chromium_gn_rel': 'gn_release_trybot', + 'mac_chromium_gn_upload': 'gn_release_bot', + }, + 'tryserver.chromium.win': { + 'win8_chromium_gn_dbg': 'gn_debug_bot', + 'win8_chromium_gn_rel': 'gn_release_trybot', + 'win8_chromium_gn_upload': 'gn_release_bot', + }, + }, +}
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py new file mode 100644 index 0000000..19cd87fa --- /dev/null +++ b/tools/mb/mb_unittest.py
@@ -0,0 +1,170 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Tests for mb.py.""" + +import json +import sys +import unittest + +import mb + + +class FakeMBW(mb.MetaBuildWrapper): + def __init__(self): + super(FakeMBW, self).__init__() + self.files = {} + self.calls = [] + self.out = '' + self.err = '' + self.chromium_src_dir = '/fake_src' + self.default_config = '/fake_src/tools/mb/mb_config.pyl' + + def ExpandUser(self, path): + return '$HOME/%s' % path + + def Exists(self, path): + return self.files.get(path) is not None + + def ReadFile(self, path): + return self.files[path] + + def WriteFile(self, path, contents): + self.files[path] = contents + + def Call(self, cmd): + self.calls.append(cmd) + return 0, '', '' + + def Print(self, *args, **kwargs): + sep = kwargs.get('sep', ' ') + end = kwargs.get('end', '\n') + f = kwargs.get('file', sys.stdout) + if f == sys.stderr: + self.err += sep.join(args) + end + else: + self.out += sep.join(args) + end + +class IntegrationTest(unittest.TestCase): + def test_validate(self): + # Note that this validates that the actual mb_config.pyl is valid. + ret = mb.main(['validate', '--quiet']) + self.assertEqual(ret, 0) + + +TEST_CONFIG = """\ +{ + 'common_dev_configs': ['gn_debug'], + 'configs': { + 'gyp_rel_bot': ['gyp', 'rel', 'goma'], + 'gn_debug': ['gn', 'debug'], + 'gn_rel_bot': ['gn', 'rel', 'goma'], + 'private': ['gyp', 'fake_feature1'], + 'unsupported': ['gn', 'fake_feature2'], + }, + 'masters': { + 'fake_master': { + 'fake_builder': 'gyp_rel_bot', + 'fake_gn_builder': 'gn_rel_bot', + }, + }, + 'mixins': { + 'fake_feature1': { + 'gn_args': 'enable_doom_melon=true', + 'gyp_defines': 'doom_melon=1', + }, + 'fake_feature2': { + 'gn_args': 'enable_doom_melon=false', + 'gyp_defaults': 'doom_melon=0', + }, + 'gyp': {'type': 'gyp'}, + 'gn': {'type': 'gn'}, + 'goma': { + 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"', + 'gyp_defines': 'goma=1 gomadir="$(goma_dir)"', + }, + 'rel': { + 'gn_args': 'is_debug=false', + 'gyp_config': 'Release', + }, + 'debug': { + 'gn_args': 'is_debug=true', + }, + }, + 'private_configs': ['private'], + 'unsupported_configs': ['unsupported'], +} +""" + + +class UnitTest(unittest.TestCase): + def fake_mbw(self, files): + mbw = FakeMBW() + if files: + for path, contents in files.items(): + mbw.files[path] = contents + mbw.files.setdefault(mbw.default_config, TEST_CONFIG) + return mbw + + def check(self, args, mbw=None, files=None, out=None, err=None, ret=None): + if not mbw: + mbw = self.fake_mbw(files) + mbw.ParseArgs(args) + actual_ret = mbw.args.func() + if ret is not None: + self.assertEqual(actual_ret, ret) + if out is not None: + self.assertEqual(mbw.out, out) + if err is not None: + self.assertEqual(mbw.err, err) + return mbw + + def test_gn_analyze(self): + files = {'/tmp/in.json': """{\ + "files": ["foo/foo_unittest.cc"], + "targets": ["foo_unittests", "bar_unittests"] + }"""} + mbw = self.fake_mbw(files) + mbw.Call = lambda cmd: (0, 'out/Default/foo_unittests\n', '') + + self.check(['analyze', '-c', 'gn_debug', '//out/Default', + '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) + out = json.loads(mbw.files['/tmp/out.json']) + self.assertEqual(out, { + 'status': 'Found dependency', + 'targets': ['foo_unittests'], + 'build_targets': ['foo_unittests'] + }) + + def test_gyp_analyze(self): + self.check(['analyze', '-c', 'gyp_rel_bot', '//out/Release', + '/tmp/in.json', '/tmp/out.json'], + ret=0) + + def test_gen(self): + self.check(['gen', '-c', 'gn_debug', '//out/Default'], ret=0) + self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], ret=0) + + def test_goma_dir_expansion(self): + self.check(['lookup', '-c', 'gyp_rel_bot', '-g', '/foo'], ret=0, + out=("python build/gyp_chromium -G 'output_dir=<path>' " + "-G config=Release -D goma=1 -D gomadir=/foo\n")) + self.check(['lookup', '-c', 'gn_rel_bot', '-g', '/foo'], ret=0, + out=("gn gen '<path>' '--args=is_debug=false use_goma=true " + "goma_dir=\"/foo\"'\n" )) + + def test_help(self): + self.assertRaises(SystemExit, self.check, ['-h']) + self.assertRaises(SystemExit, self.check, ['help']) + self.assertRaises(SystemExit, self.check, ['help', 'gen']) + + def test_lookup(self): + self.check(['lookup', '-c', 'gn_debug'], ret=0) + + def test_validate(self): + self.check(['validate'], ret=0) + + +if __name__ == '__main__': + unittest.main()
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 5275953d..6faf7677 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -11302,6 +11302,14 @@ </summary> </histogram> +<histogram name="GPU.TextureRG" enum="BooleanAvailable"> + <owner>reveman@chromium.org</owner> + <summary> + Whether RG texture support is available. Recorded each time a new context + group is initialized and extensions are detected. + </summary> +</histogram> + <histogram name="Hardware.Display.Count.OnChange"> <owner>erikchen@chromium.org</owner> <summary> @@ -13481,6 +13489,18 @@ </summary> </histogram> +<histogram name="ManagedUsers.FilteringResult" + enum="SupervisedUserSafetyFilterResult"> + <owner>treib@chromium.org</owner> + <owner>pam@chromium.org</owner> + <summary> + The counts of results from supervised user URL filtering. Each entry + includes the outcome of the filter (i.e. allowed, blocked, or unknown) and + the page transition type (how the user got there, e.g. typed URL, clicked + link). + </summary> +</histogram> + <histogram name="ManagedUsers.SafeSitesDelay" units="milliseconds"> <owner>treib@chromium.org</owner> <owner>pam@chromium.org</owner> @@ -13498,8 +13518,8 @@ The counts of results from the supervised user safety filter. Each entry includes the outcome of the filter (i.e. allowed, blocked, or unknown) and the page transition type (how the user got there, e.g. typed URL, clicked - link). This only includes URL requests that were not handled by a manual - exception. + link). This only includes URL requests that were handled by the SafeSites + filter (both online and the static blacklist). </summary> </histogram> @@ -43727,22 +43747,24 @@ </histogram> <histogram name="WebCore.Scripts.Async.NotStreamingReason" - units="NotStreamingReason"> + enum="NotStreamingReason"> <owner>marja@chromium.org</owner> <summary>Reason for not streaming an async script.</summary> </histogram> -<histogram name="WebCore.Scripts.Async.StartedStreaming" - units="BooleanStreamed"> +<histogram name="WebCore.Scripts.Async.StartedStreaming" enum="BooleanStreamed"> <owner>marja@chromium.org</owner> <summary>Whether an async script was streamed or not.</summary> </histogram> +<histogram name="WebCore.Scripts.Deferred.NotStreamingReason" + enum="NotStreamingReason"> + <owner>marja@chromium.org</owner> + <summary>Reason for not streaming a deferred script.</summary> +</histogram> + <histogram name="WebCore.Scripts.Deferred.StartedStreaming" - units="BooleanStreamed"> - <obsolete> - Deprecated as deferred scripts are not streamed. - </obsolete> + enum="BooleanStreamed"> <owner>marja@chromium.org</owner> <summary>Whether a deferred script was streamed or not.</summary> </histogram> @@ -43760,11 +43782,14 @@ </summary> </histogram> +<histogram name="WebCore.Scripts.ParsingBlocking.NotStreamingReason" + enum="NotStreamingReason"> + <owner>marja@chromium.org</owner> + <summary>Reason for not streaming a parsing blocking script.</summary> +</histogram> + <histogram name="WebCore.Scripts.ParsingBlocking.StartedStreaming" - units="BooleanStreamed"> - <obsolete> - Deprecated as parsing blocking scripts are not streamed. - </obsolete> + enum="BooleanStreamed"> <owner>marja@chromium.org</owner> <summary>Whether a parsing blocking script was streamed or not.</summary> </histogram> @@ -45998,6 +46023,7 @@ <int value="14" label="SERVICE_WORKER_BAD_URL"/> <int value="15" label="WC_INVALID_FRAME_SOURCE"/> <int value="16" label="RWHVM_UNEXPECTED_FRAME_TYPE"/> + <int value="17" label="DFH_BAD_EMBEDDER_MESSAGE"/> </enum> <enum name="BadMessageReasonExtensions" type="int"> @@ -48960,6 +48986,7 @@ <int value="296" label="Set Apps and Extensions cache size (in bytes)"/> <int value="297" label="Show an autocomplete option during user sign-in flow"/> + <int value="298" label="Maximize the first browser window on first run"/> </enum> <enum name="EnterprisePolicyInvalidations" type="int"> @@ -48969,8 +48996,8 @@ </summary> <int value="0" label="No payload; not expired"/> <int value="1" label="Payload; not expired"/> - <int value="2" label="No payload; expired"/> - <int value="3" label="Payload; expired"/> + <int value="3" label="No payload; expired"/> + <int value="4" label="Payload; expired"/> </enum> <enum name="EnterprisePolicyLoadStatus" type="int"> @@ -59986,7 +60013,7 @@ <int value="13" label="DICTIONARY_FOUND_HAS_WRONG_SCHEME"/> <int value="14" label="DICTIONARY_HASH_NOT_FOUND"/> <int value="15" label="DICTIONARY_HASH_MALFORMED"/> - <int value="16" label="DICTIONARY_FOUND_EXPIRED"/> + <int value="16" label="defunct (DICTIONARY_FOUND_EXPIRED)"/> <int value="20" label="DICTIONARY_HAS_NO_HEADER"/> <int value="21" label="DICTIONARY_HEADER_LINE_MISSING_COLON"/> <int value="22" label="DICTIONARY_MISSING_DOMAIN_SPECIFIER"/> @@ -60041,11 +60068,13 @@ <int value="78" label="PASS_THROUGH_404_CODE"/> <int value="79" label="PASS_THROUGH_OLD_CACHED"/> <int value="80" label="META_REFRESH_CACHED_RECOVERY"/> - <int value="81" label="DISCARD_TENTATIVE_SDCH"/> - <int value="90" label="UNFLUSHED_CONTENT"/> + <int value="81" label="defunct (DISCARD_TENTATIVE_SDCH)"> + Now tracked by ResponseCorruptionDetection.* histograms. + </int> + <int value="90" label="defunct (UNFLUSHED_CONTENT)"/> <int value="91" label="MISSING_TIME_STATS"/> <int value="92" label="CACHE_DECODED"/> - <int value="93" label="OVER_10_MINUTES"/> + <int value="93" label="defunct (OVER_10_MINUTES)"/> <int value="94" label="UNINITIALIZED"/> <int value="95" label="PRIOR_TO_DICTIONARY"/> <int value="96" label="DECODE_ERROR"/> @@ -61705,6 +61734,78 @@ <int value="499" label="OTHER_BLOCKED_SAFESITES"> Other navigation; Blocked by SafeSites </int> + <int value="500" label="LINK_BLOCKED_MANUAL"> + Link; Blocked by manual exception + </int> + <int value="501" label="TYPED_BLOCKED_MANUAL"> + Typed URL; Blocked by manual exception + </int> + <int value="502" label="AUTO_BOOKMARK_BLOCKED_MANUAL"> + Bookmark; Blocked by manual exception + </int> + <int value="503" label="AUTO_SUBFRAME_BLOCKED_MANUAL"> + Subframe navigation; Blocked by manual exception + </int> + <int value="504" label="MANUAL_SUBFRAME_BLOCKED_MANUAL"> + Manual subframe navigation; Blocked by manual exception + </int> + <int value="505" label="GENERATED_BLOCKED_MANUAL"> + Generated from Omnibox; Blocked by manual exception + </int> + <int value="506" label="AUTO_TOPLEVEL_BLOCKED_MANUAL"> + Automatic toplevel navigation; Blocked by manual exception + </int> + <int value="507" label="FORM_SUBMIT_BLOCKED_MANUAL"> + Form submission; Blocked by manual exception + </int> + <int value="508" label="RELOAD_BLOCKED_MANUAL"> + Reload; Blocked by manual exception + </int> + <int value="509" label="KEYWORD_BLOCKED_MANUAL"> + Omnibox keyword; Blocked by manual exception + </int> + <int value="510" label="KEYWORD_GENERATED_BLOCKED_MANUAL"> + URL generated from Omnibox keyword; Blocked by manual exception + </int> + <int value="599" label="OTHER_BLOCKED_MANUAL"> + Other navigation; Blocked by manual exception + </int> + <int value="600" label="LINK_BLOCKED_DEFAULT"> + Link; Blocked by global settings + </int> + <int value="601" label="TYPED_BLOCKED_DEFAULT"> + Typed URL; Blocked by global settings + </int> + <int value="602" label="AUTO_BOOKMARK_BLOCKED_DEFAULT"> + Bookmark; Blocked by global settings + </int> + <int value="603" label="AUTO_SUBFRAME_BLOCKED_DEFAULT"> + Subframe navigation; Blocked by global settings + </int> + <int value="604" label="MANUAL_SUBFRAME_BLOCKED_DEFAULT"> + Manual subframe navigation; Blocked by global settings + </int> + <int value="605" label="GENERATED_BLOCKED_DEFAULT"> + Generated from Omnibox; Blocked by global settings + </int> + <int value="606" label="AUTO_TOPLEVEL_BLOCKED_DEFAULT"> + Automatic toplevel navigation; Blocked by global settings + </int> + <int value="607" label="FORM_SUBMIT_BLOCKED_DEFAULT"> + Form submission; Blocked by global settings + </int> + <int value="608" label="RELOAD_BLOCKED_DEFAULT"> + Reload; Blocked by global settings + </int> + <int value="609" label="KEYWORD_BLOCKED_DEFAULT"> + Omnibox keyword; Blocked by global settings + </int> + <int value="610" label="KEYWORD_GENERATED_BLOCKED_DEFAULT"> + URL generated from Omnibox keyword; Blocked by global settings + </int> + <int value="699" label="OTHER_BLOCKED_DEFAULT"> + Other navigation; Blocked by global settings + </int> </enum> <enum name="SuspendAttempt" type="int">
diff --git a/tools/metrics/rappor/rappor.xml b/tools/metrics/rappor/rappor.xml index c10a418..49b1f1e 100644 --- a/tools/metrics/rappor/rappor.xml +++ b/tools/metrics/rappor/rappor.xml
@@ -356,6 +356,22 @@ </summary> </rappor-metric> +<rappor-metric name="WebComponents.DocumentRegisterElement" + type="ETLD_PLUS_ONE"> + <owner>kojii@chromium.org</owner> + <summary> + The host of a URL that used Document::RegisterElement(). + </summary> +</rappor-metric> + +<rappor-metric name="WebComponents.ElementCreateShadowRoot" + type="ETLD_PLUS_ONE"> + <owner>kojii@chromium.org</owner> + <summary> + The host of a URL that used Element::CreateShadowRoot(). + </summary> +</rappor-metric> + <rappor-metric name="interstitial.harmful.domain" type="COARSE_RAPPOR_TYPE"> <owner>nparker@chromium.org</owner> <summary>
diff --git a/tools/perf/benchmarks/memory.py b/tools/perf/benchmarks/memory.py index b5eb386..44b900a 100644 --- a/tools/perf/benchmarks/memory.py +++ b/tools/perf/benchmarks/memory.py
@@ -26,3 +26,18 @@ @classmethod def Name(cls): return 'memory.top_7_stress' + + +class MemoryTop7StressWithSlimmingPaint(benchmark.Benchmark): + """Use (recorded) real world web sites and measure memory consumption, + with --enable--slimming-paint.""" + + test = memory.Memory + page_set = page_sets.Top7StressPageSet + + def CustomizeBrowserOptions(self, options): + options.AppendExtraBrowserArgs(['--enable-slimming-paint']) + + @classmethod + def Name(cls): + return 'memory.top_7_stress_slimming_paint'
diff --git a/tools/perf/benchmarks/page_cycler.py b/tools/perf/benchmarks/page_cycler.py index 3986218..a3c6572 100644 --- a/tools/perf/benchmarks/page_cycler.py +++ b/tools/perf/benchmarks/page_cycler.py
@@ -58,7 +58,8 @@ return 'page_cycler.intl_ar_fa_he' -@benchmark.Disabled('win') # crbug.com/366715 +@benchmark.Disabled('win', # crbug.com/366715 + 'android') # crbug.com/474696 class PageCyclerIntlEsFrPtBr(_PageCycler): """Page load time for a pages in Spanish, French and Brazilian Portuguese.
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py index 9cbda538..8d83f0a 100644 --- a/tools/perf/benchmarks/power.py +++ b/tools/perf/benchmarks/power.py
@@ -8,7 +8,7 @@ import page_sets -@benchmark.Enabled('android') +@benchmark.Disabled('android') # crbug.com/474696 class PowerAndroidAcceptance(benchmark.Benchmark): """Android power acceptance test.""" test = power.Power @@ -19,7 +19,7 @@ -@benchmark.Enabled('android') +@benchmark.Disabled('android') # crbug.com/474696 class PowerTypical10Mobile(benchmark.Benchmark): """Android typical 10 mobile power test.""" test = power.Power
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index 067825bd..45ab9ba 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -216,6 +216,17 @@ return 'smoothness.tough_pinch_zoom_cases' +@benchmark.Enabled('chromeos') +class SmoothnessToughScrollingWhileZoomedInCases(benchmark.Benchmark): + """Measures rendering statistics for pinch-zooming then diagonal scrolling""" + test = smoothness.Smoothness + page_set = page_sets.ToughScrollingWhileZoomedInCasesPageSet + + @classmethod + def Name(cls): + return 'smoothness.tough_scrolling_while_zoomed_in_cases' + + @benchmark.Enabled('android') class SmoothnessPolymer(benchmark.Benchmark): """Measures rendering statistics for Polymer cases.
diff --git a/tools/perf/measurements/smoothness_controller.py b/tools/perf/measurements/smoothness_controller.py index 20fbb1e6..89521a0 100644 --- a/tools/perf/measurements/smoothness_controller.py +++ b/tools/perf/measurements/smoothness_controller.py
@@ -13,10 +13,9 @@ from telemetry.value import scalar from telemetry.value import trace from telemetry.web_perf.metrics import smoothness +from telemetry.web_perf import smooth_gesture_util from telemetry.web_perf import timeline_interaction_record as tir_module -from measurements import smooth_gesture_util - RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions'
diff --git a/tools/perf/measurements/timeline_controller.py b/tools/perf/measurements/timeline_controller.py index 0ddca5e..3b0db0a 100644 --- a/tools/perf/measurements/timeline_controller.py +++ b/tools/perf/measurements/timeline_controller.py
@@ -7,10 +7,9 @@ from telemetry.page import action_runner from telemetry.timeline.model import TimelineModel from telemetry.value import trace +from telemetry.web_perf import smooth_gesture_util from telemetry.web_perf import timeline_interaction_record as tir_module -from measurements import smooth_gesture_util - RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions'
diff --git a/tools/perf/page_sets/diagonal_scrolling_supported_shared_state.py b/tools/perf/page_sets/diagonal_scrolling_supported_shared_state.py new file mode 100644 index 0000000..969fca8 --- /dev/null +++ b/tools/perf/page_sets/diagonal_scrolling_supported_shared_state.py
@@ -0,0 +1,15 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import logging + +from telemetry.page import shared_page_state + + +class DiagonalScrollingSupportedSharedState(shared_page_state.SharedPageState): + def CanRunOnBrowser(self, browser_info): + if not browser_info.HasDiagonalScrollingSupport(): + logging.warning('Browser does not support synthetic diagonal scrolling,' + ' skipping test') + return False + return True
diff --git a/tools/perf/page_sets/key_hit_test_cases.py b/tools/perf/page_sets/key_hit_test_cases.py index f573d10..a1e214a 100644 --- a/tools/perf/page_sets/key_hit_test_cases.py +++ b/tools/perf/page_sets/key_hit_test_cases.py
@@ -5,44 +5,39 @@ from telemetry.page import page as page_module from telemetry.page import page_set as page_set_module +from page_sets import polymer -class KeyHitTestCasesPage(page_module.Page): - - def __init__(self, url, page_set): - super(KeyHitTestCasesPage, self).__init__( - url=url, page_set=page_set, credentials_path = 'data/credentials.json') - self.user_agent_type = 'mobile' - - def RunNavigateSteps(self, action_runner): - super(KeyHitTestCasesPage, self).RunNavigateSteps(action_runner) - action_runner.Wait(2) - - def RunPageInteractions(self, action_runner): - action_runner.Wait(2) - for _ in xrange(100): - self.TapButton(action_runner) - - -class PaperCalculatorHitTest(KeyHitTestCasesPage): +class PaperCalculatorHitTest(polymer.PolymerPage): def __init__(self, page_set): super(PaperCalculatorHitTest, self).__init__( # Generated from https://github.com/zqureshi/paper-calculator # vulcanize --inline --strip paper-calculator/demo.html url='file://key_hit_test_cases/paper-calculator-no-rendering.html', - page_set=page_set) + page_set=page_set, run_no_page_interactions=False) - def TapButton(self, action_runner): - interaction = action_runner.BeginInteraction( - 'Action_TapAction') - action_runner.TapElement(element_function=''' - document.querySelector( + self.user_agent_type = 'mobile' + + def PerformPageInteractions(self, action_runner): + # pay cost of selecting tap target only once + action_runner.ExecuteJavaScript(''' + window.__tapTarget = document.querySelector( 'body /deep/ #outerPanels' ).querySelector( '#standard' ).shadowRoot.querySelector( 'paper-calculator-key[label="5"]' )''') + action_runner.WaitForJavaScriptCondition( + 'window.__tapTarget != null') + + for _ in xrange(100): + self.TapButton(action_runner) + + def TapButton(self, action_runner): + interaction = action_runner.BeginInteraction( + 'Action_TapAction') + action_runner.TapElement(element_function='''window.__tapTarget''') interaction.End()
diff --git a/tools/perf/page_sets/key_silk_cases/masonry.html b/tools/perf/page_sets/key_silk_cases/masonry.html index ac9fa2ad..c4d8ecb 100644 --- a/tools/perf/page_sets/key_silk_cases/masonry.html +++ b/tools/perf/page_sets/key_silk_cases/masonry.html
@@ -1116,7 +1116,7 @@ }(window); var container = document.querySelector('#container'); var item = container.children[0]; -for (var i = 0; i < 100; ++i) { +for (var i = 0; i < 20; ++i) { container.appendChild(item.cloneNode(true)); } document.body.style.display = 'block'; @@ -1125,12 +1125,23 @@ var mason = new Masonry(container, { itemSelector: '.item', }); - requestAnimationFrame(function() { - mason.element.style.maxWidth = '950px'; - mason.layout(); - requestAnimationFrame(function() { + function relayout(i) { + if (i === 30) { window.done = true; + return; + } + requestAnimationFrame(function() { + mason.element.style.maxWidth = '950px'; + mason.layout(); + requestAnimationFrame(function() { + mason.element.style.maxWidth = '200px'; + mason.layout(); + requestAnimationFrame(function() { + relayout(i + 1); + }); + }); }); - }); + } + relayout(0); }; </script>
diff --git a/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py b/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py new file mode 100644 index 0000000..14a79fdc --- /dev/null +++ b/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py
@@ -0,0 +1,64 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +from page_sets import diagonal_scrolling_supported_shared_state + +from telemetry.page import shared_page_state +from telemetry.page import page as page_module +from telemetry.page import page_set as page_set_module +from telemetry.core.backends.chrome_inspector import devtools_client_backend + + +class ToughScrollingWhileZoomedInCasesPage(page_module.Page): + + def __init__(self, url, page_set): + super(ToughScrollingWhileZoomedInCasesPage, self).__init__( + url=url, + page_set=page_set, + shared_page_state_class=( + diagonal_scrolling_supported_shared_state. + DiagonalScrollingSupportedSharedState)) + + def RunPageInteractions(self, action_runner): + # First, zoom into the page + action_runner.PinchPage( + scale_factor=20.0, + speed_in_pixels_per_second=10000) + # 20.0 was chosen because at the time it was close to the maximum. + # The more zoomed in, the more noticable the tile rasterization. + # + # 10,000 was chosen to complete this pre-step quickly. + + # Then start measurements + interaction = action_runner.BeginGestureInteraction('ScrollAction') + # And begin the diagonal scroll + action_runner.ScrollPage( + direction='downright', + speed_in_pixels_per_second=10000) + # 10,000 was chosen because it is fast enough to completely stress the + # rasterization (on a Nexus 5) without saturating results. + interaction.End() + + +class ToughScrollingWhileZoomedInCasesPageSet(page_set_module.PageSet): + """ + Description: A collection of difficult scrolling tests + """ + + def __init__(self): + super(ToughScrollingWhileZoomedInCasesPageSet, self).__init__( + user_agent_type='desktop', + archive_data_file='data/tough_pinch_zoom_cases.json', + bucket=page_set_module.PARTNER_BUCKET) + + # The following urls were chosen because they tend to have >15% + # mean_pixels_approximated at this scrolling speed. + urls_list = [ + 'file://tough_scrolling_cases/background_fixed.html', + 'file://tough_scrolling_cases/fixed_nonstacking.html', + 'file://tough_scrolling_cases/iframe_scrolls.html', + 'file://tough_scrolling_cases/wheel_div_prevdefault.html' + ] + + for url in urls_list: + self.AddUserStory(ToughScrollingWhileZoomedInCasesPage(url, self))
diff --git a/tools/telemetry/telemetry/core/browser_info.py b/tools/telemetry/telemetry/core/browser_info.py index 4a99c6b..c51a8f9 100644 --- a/tools/telemetry/telemetry/core/browser_info.py +++ b/tools/telemetry/telemetry/core/browser_info.py
@@ -45,3 +45,10 @@ branch_num = ( self._browser._browser_backend.devtools_client.GetChromeBranchNumber()) return branch_num >= 2339 + + def HasDiagonalScrollingSupport(self): + # Diagonal scrolling was not supported in the ScrollAction until + # Chromium branch number 2332 + branch_num = ( + self._browser._browser_backend.devtools_client.GetChromeBranchNumber()) + return branch_num >= 2332
diff --git a/tools/telemetry/telemetry/internal/actions/action_runner_unittest.py b/tools/telemetry/telemetry/internal/actions/action_runner_unittest.py index d4da4e0..da984667 100644 --- a/tools/telemetry/telemetry/internal/actions/action_runner_unittest.py +++ b/tools/telemetry/telemetry/internal/actions/action_runner_unittest.py
@@ -1,10 +1,12 @@ # Copyright 2014 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import unittest from telemetry.core import exceptions from telemetry.core.platform import tracing_category_filter from telemetry.core.platform import tracing_options +from telemetry.core import util from telemetry import decorators from telemetry.internal.actions import page_action from telemetry.page import action_runner as action_runner_module @@ -12,6 +14,9 @@ from telemetry.unittest_util import tab_test_case from telemetry.web_perf import timeline_interaction_record as tir_module +util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock') +import mock + class ActionRunnerInteractionTest(tab_test_case.TabTestCase): @@ -33,9 +38,9 @@ options.enable_chrome_trace = True self._browser.platform.tracing_controller.Start( options, tracing_category_filter.CreateNoOverheadFilter()) - interaction = action_runner.BeginInteraction('InteractionName', - **interaction_kwargs) - interaction.End() + with action_runner.CreateInteraction('InteractionName', + **interaction_kwargs): + pass trace_data = self._browser.platform.tracing_controller.Stop() records = self.GetInteractionRecords(trace_data) @@ -248,3 +253,34 @@ action_runner.SwipePage(direction='left', left_start_ratio=0.9) self.assertTrue(action_runner.EvaluateJavaScript( 'document.body.scrollLeft') > 75) + + +class InteractionTest(unittest.TestCase): + + def setUp(self): + self.mock_action_runner = mock.Mock(action_runner_module.ActionRunner) + + def testIssuingInteractionRecordCommand(self): + with action_runner_module.Interaction( + self.mock_action_runner, label='ABC', flags=[]): + pass + expected_calls = [ + mock.call.ExecuteJavaScript('console.time("Interaction.ABC");'), + mock.call.ExecuteJavaScript('console.timeEnd("Interaction.ABC");')] + self.assertEqual(expected_calls, self.mock_action_runner.mock_calls) + + def testExceptionRaisedInWithInteraction(self): + class FooException(Exception): + pass + # Test that the Foo exception raised in the with block is propagated to the + # caller. + with self.assertRaises(FooException): + with action_runner_module.Interaction( + self.mock_action_runner, label='ABC', flags=[]): + raise FooException() + + # Test that the end console.timeEnd(...) isn't called because exception was + # raised. + expected_calls = [ + mock.call.ExecuteJavaScript('console.time("Interaction.ABC");')] + self.assertEqual(expected_calls, self.mock_action_runner.mock_calls)
diff --git a/tools/telemetry/telemetry/internal/actions/scroll.js b/tools/telemetry/telemetry/internal/actions/scroll.js index 77beb678..04d2569 100644 --- a/tools/telemetry/telemetry/internal/actions/scroll.js +++ b/tools/telemetry/telemetry/internal/actions/scroll.js
@@ -41,43 +41,71 @@ function ScrollAction(opt_callback, opt_distance_func) { var self = this; - this.beginMeasuringHook = function() {} - this.endMeasuringHook = function() {} + this.beginMeasuringHook = function() {}; + this.endMeasuringHook = function() {}; this.callback_ = opt_callback; this.distance_func_ = opt_distance_func; } + ScrollAction.prototype.getScrollDistanceDown_ = function() { + var clientHeight; + // clientHeight is "special" for the body element. + if (this.element_ == document.body) + clientHeight = window.innerHeight; + else + clientHeight = this.element_.clientHeight; + + return this.element_.scrollHeight - + this.element_.scrollTop - + clientHeight; + }; + + ScrollAction.prototype.getScrollDistanceUp_ = function() { + return this.element_.scrollTop; + }; + + ScrollAction.prototype.getScrollDistanceRight_ = function() { + var clientWidth; + // clientWidth is "special" for the body element. + if (this.element_ == document.body) + clientWidth = window.innerWidth; + else + clientWidth = this.element_.clientWidth; + + return this.element_.scrollWidth - this.element_.scrollLeft - clientWidth; + }; + + ScrollAction.prototype.getScrollDistanceLeft_ = function() { + return this.element_.scrollLeft; + }; + ScrollAction.prototype.getScrollDistance_ = function() { if (this.distance_func_) return this.distance_func_(); if (this.options_.direction_ == 'down') { - var clientHeight; - // clientHeight is "special" for the body element. - if (this.element_ == document.body) - clientHeight = window.innerHeight; - else - clientHeight = this.element_.clientHeight; - - return this.element_.scrollHeight - - this.element_.scrollTop - - clientHeight; + return this.getScrollDistanceDown_(); } else if (this.options_.direction_ == 'up') { - return this.element_.scrollTop; + return this.getScrollDistanceUp_(); } else if (this.options_.direction_ == 'right') { - var clientWidth; - // clientWidth is "special" for the body element. - if (this.element_ == document.body) - clientWidth = window.innerWidth; - else - clientWidth = this.element_.clientWidth; - - return this.element_.scrollWidth - this.element_.scrollLeft - clientWidth; + return this.getScrollDistanceRight_(); } else if (this.options_.direction_ == 'left') { - return this.element_.scrollLeft; + return this.getScrollDistanceLeft_(); + } else if (this.options_.direction_ == 'upleft') { + return Math.min(this.getScrollDistanceUp_(), + this.getScrollDistanceLeft_()); + } else if (this.options_.direction_ == 'upright') { + return Math.min(this.getScrollDistanceUp_(), + this.getScrollDistanceRight_()); + } else if (this.options_.direction_ == 'downleft') { + return Math.min(this.getScrollDistanceDown_(), + this.getScrollDistanceLeft_()); + } else if (this.options_.direction_ == 'downright') { + return Math.min(this.getScrollDistanceDown_(), + this.getScrollDistanceRight_()); } - } + }; ScrollAction.prototype.start = function(opt_options) { this.options_ = new ScrollGestureOptions(opt_options);
diff --git a/tools/telemetry/telemetry/internal/actions/scroll.py b/tools/telemetry/telemetry/internal/actions/scroll.py index 4d5cb10e3..2541098 100644 --- a/tools/telemetry/telemetry/internal/actions/scroll.py +++ b/tools/telemetry/telemetry/internal/actions/scroll.py
@@ -14,7 +14,9 @@ distance=None, distance_expr=None, speed_in_pixels_per_second=800, use_touch=False): super(ScrollAction, self).__init__() - if direction not in ['down', 'up', 'left', 'right']: + if direction not in ('down', 'up', 'left', 'right', + 'downleft', 'downright', + 'upleft', 'upright'): raise page_action.PageActionNotSupported( 'Invalid scroll direction: %s' % self.direction) self._selector = selector @@ -35,6 +37,14 @@ distance_expr) def WillRunAction(self, tab): + if self._direction in ('downleft', 'downright', 'upleft', 'upright'): + # Diagonal scrolling support was added in Chrome branch number 2332. + branch_num = ( + tab.browser._browser_backend.devtools_client.GetChromeBranchNumber()) + if branch_num < 2332: + raise ValueError('Diagonal scrolling requires Chrome branch number' + ' 2332 or later. Found branch number %d' % + branch_num) for js_file in ['gesture_common.js', 'scroll.js']: with open(os.path.join(os.path.dirname(__file__), js_file)) as f: js = f.read()
diff --git a/tools/telemetry/telemetry/internal/actions/scroll_unittest.py b/tools/telemetry/telemetry/internal/actions/scroll_unittest.py index 66c6681..29bd28570 100644 --- a/tools/telemetry/telemetry/internal/actions/scroll_unittest.py +++ b/tools/telemetry/telemetry/internal/actions/scroll_unittest.py
@@ -7,7 +7,7 @@ from telemetry import decorators from telemetry.internal.actions import scroll from telemetry.unittest_util import tab_test_case - +from telemetry.core.backends.chrome_inspector import devtools_client_backend class ScrollActionTest(tab_test_case.TabTestCase): def testScrollAction(self): @@ -41,6 +41,42 @@ self.assertTrue(scroll_position != 0, msg='scroll_position=%d;' % (scroll_position)) + def testDiagonalScrollAction(self): + # Diagonal scrolling was not supported in the ScrollAction until Chrome + # branch number 2332 + branch_num = self._tab.browser._browser_backend.devtools_client \ + .GetChromeBranchNumber() + if branch_num < 2332: + return + + self.Navigate('blank.html') + + # Make page bigger than window so it's scrollable. + self._tab.ExecuteJavaScript("""document.body.style.height = + (2 * window.innerHeight + 1) + 'px';""") + self._tab.ExecuteJavaScript("""document.body.style.width = + (2 * window.innerWidth + 1) + 'px';""") + + self.assertEquals( + self._tab.EvaluateJavaScript("""document.documentElement.scrollTop + || document.body.scrollTop"""), 0) + self.assertEquals( + self._tab.EvaluateJavaScript("""document.documentElement.scrollLeft + || document.body.scrollLeft"""), 0) + + i = scroll.ScrollAction(direction='downright') + i.WillRunAction(self._tab) + + i.RunAction(self._tab) + + viewport_top = self._tab.EvaluateJavaScript( + '(document.documentElement.scrollTop || document.body.scrollTop)') + self.assertTrue(viewport_top != 0, msg='viewport_top=%d;' % viewport_top) + + viewport_left = self._tab.EvaluateJavaScript( + '(document.documentElement.scrollLeft || document.body.scrollLeft)') + self.assertTrue(viewport_left != 0, msg='viewport_left=%d;' % viewport_left) + def testBoundingClientRect(self): self.Navigate('blank.html')
diff --git a/tools/telemetry/telemetry/page/action_runner.py b/tools/telemetry/telemetry/page/action_runner.py index 21825122..6687a28a 100644 --- a/tools/telemetry/telemetry/page/action_runner.py +++ b/tools/telemetry/telemetry/page/action_runner.py
@@ -6,6 +6,7 @@ import time import urlparse +from telemetry.core import exceptions from telemetry.internal.actions.drag import DragAction from telemetry.internal.actions.javascript_click import ClickElementAction from telemetry.internal.actions.loop import LoopAction @@ -34,6 +35,7 @@ action.WillRunAction(self._tab) action.RunAction(self._tab) + # TODO(nednguyen): remove this API when crbug.com/475090 is fixed. def BeginInteraction(self, label, repeatable=False): """Marks the beginning of an interaction record. @@ -58,6 +60,7 @@ interaction.Begin() return interaction + # TODO(nednguyen): remove this API when crbug.com/475090 is fixed. def BeginGestureInteraction(self, label, repeatable=False): """Marks the beginning of a gesture-based interaction record. @@ -78,6 +81,67 @@ """ return self.BeginInteraction('Gesture_' + label, repeatable) + def CreateInteraction(self, label, repeatable=False): + """ Create an action.Interaction object that issues interaction record. + + An interaction record is a labeled time period containing + interaction that developers care about. Each set of metrics + specified in flags will be calculated for this time period. + + To mark the start of interaction record, call Begin() method on the returned + object. To mark the finish of interaction record, call End() method on + it. Or better yet, use the with statement to create an + interaction record that covers the actions in the with block. + + e.g: + with action_runner.CreateInteraction('Animation-1'): + action_runner.TapElement(...) + action_runner.WaitForJavaScriptCondition(...) + + Args: + label: A label for this particular interaction. This can be any + user-defined string, but must not contain '/'. + repeatable: Whether other interactions may use the same logical name + as this interaction. All interactions with the same logical name must + have the same flags. + + Returns: + An instance of action_runner.Interaction + """ + flags = [] + if repeatable: + flags.append(timeline_interaction_record.REPEATABLE) + + return Interaction(self._tab, label, flags) + + def CreateGestureInteraction(self, label, repeatable=False): + """ Create an action.Interaction object that issues gesture-based + interaction record. + + This is similar to normal interaction record, but it will + auto-narrow the interaction time period to only include the + synthetic gesture event output by Chrome. This is typically use to + reduce noise in gesture-based analysis (e.g., analysis for a + swipe/scroll). + + The interaction record label will be prepended with 'Gesture_'. + + e.g: + with action_runner.CreateGestureInteraction('Scroll-1'): + action_runner.ScrollPage() + + Args: + label: A label for this particular interaction. This can be any + user-defined string, but must not contain '/'. + repeatable: Whether other interactions may use the same logical name + as this interaction. All interactions with the same logical name must + have the same flags. + + Returns: + An instance of action_runner.Interaction + """ + return self.CreateInteraction('Gesture_' + label, repeatable) + def NavigateToPage(self, page, timeout_in_seconds=60): """Navigates to the given page. @@ -332,7 +396,7 @@ gesture, as a ratio of the visible bounding rectangle for document.body. direction: The direction of scroll, either 'left', 'right', - 'up', or 'down' + 'up', 'down', 'upleft', 'upright', 'downleft', or 'downright' distance: The distance to scroll (in pixel). distance_expr: A JavaScript expression (as string) that can be evaluated to compute scroll distance. Example: @@ -372,7 +436,7 @@ gesture, as a ratio of the visible bounding rectangle for the element. direction: The direction of scroll, either 'left', 'right', - 'up', or 'down' + 'up', 'down', 'upleft', 'upright', 'downleft', or 'downright' distance: The distance to scroll (in pixel). distance_expr: A JavaScript expression (as string) that can be evaluated to compute scroll distance. Example: @@ -406,7 +470,7 @@ gesture, as a ratio of the visible bounding rectangle for document.body. direction: The direction of scroll, either 'left', 'right', - 'up', or 'down' + 'up', 'down', 'upleft', 'upright', 'downleft', or 'downright' distance: The distance to scroll (in pixel). overscroll: The number of additional pixels to scroll back, in addition to the givendistance. @@ -444,7 +508,7 @@ gesture, as a ratio of the visible bounding rectangle for document.body. direction: The direction of scroll, either 'left', 'right', - 'up', or 'down' + 'up', 'down', 'upleft', 'upright', 'downleft', or 'downright' distance: The distance to scroll (in pixel). overscroll: The number of additional pixels to scroll back, in addition to the givendistance. @@ -624,6 +688,18 @@ self._flags = flags self._started = False + def __enter__(self): + self.Begin() + return self + + def __exit__(self, exc_type, exc_value, traceback): + if exc_value is None: + self.End() + else: + logging.warning( + 'Exception was raised in the with statement block, the end of ' + 'interaction record is not marked.') + def Begin(self): assert not self._started self._started = True
diff --git a/tools/perf/measurements/smooth_gesture_util.py b/tools/telemetry/telemetry/web_perf/smooth_gesture_util.py similarity index 100% rename from tools/perf/measurements/smooth_gesture_util.py rename to tools/telemetry/telemetry/web_perf/smooth_gesture_util.py
diff --git a/tools/perf/measurements/smooth_gesture_util_unittest.py b/tools/telemetry/telemetry/web_perf/smooth_gesture_util_unittest.py similarity index 98% rename from tools/perf/measurements/smooth_gesture_util_unittest.py rename to tools/telemetry/telemetry/web_perf/smooth_gesture_util_unittest.py index e0b9781e..a305f396 100644 --- a/tools/perf/measurements/smooth_gesture_util_unittest.py +++ b/tools/telemetry/telemetry/web_perf/smooth_gesture_util_unittest.py
@@ -13,8 +13,7 @@ from telemetry.timeline import model as model_module from telemetry.unittest_util import page_test_test_case from telemetry.web_perf import timeline_interaction_record as tir_module - -from measurements import smooth_gesture_util as sg_util +from telemetry.web_perf import smooth_gesture_util as sg_util class SmoothGestureUtilTest(unittest.TestCase):
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py index cf7aeb5..89da732ac 100644 --- a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py +++ b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
@@ -12,6 +12,7 @@ from telemetry.web_perf.metrics import responsiveness_metric from telemetry.web_perf.metrics import smoothness from telemetry.web_perf import timeline_interaction_record as tir_module +from telemetry.web_perf import smooth_gesture_util # TimelineBasedMeasurement considers all instrumentation as producing a single # timeline. But, depending on the amount of instrumentation that is enabled, @@ -68,6 +69,11 @@ # TODO(nduca): Add support for page-load interaction record. if tir_module.IsTimelineInteractionRecord(event.name): interaction = tir_module.TimelineInteractionRecord.FromAsyncEvent(event) + # Adjust the interaction record to match the synthetic gesture + # controller if needed. + interaction = ( + smooth_gesture_util.GetAdjustedInteractionIfContainGesture( + model, interaction)) threads_to_records_map[curr_thread].append(interaction) if interaction.label in interaction_labels_of_previous_threads: raise InvalidInteractions(
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_page_test_unittest.py b/tools/telemetry/telemetry/web_perf/timeline_based_page_test_unittest.py index 1c3f375..357c0a1 100644 --- a/tools/telemetry/telemetry/web_perf/timeline_based_page_test_unittest.py +++ b/tools/telemetry/telemetry/web_perf/timeline_based_page_test_unittest.py
@@ -14,12 +14,14 @@ class TestTimelinebasedMeasurementPage(page_module.Page): def __init__(self, ps, base_dir, trigger_animation=False, - trigger_jank=False, trigger_slow=False): + trigger_jank=False, trigger_slow=False, + trigger_scroll_gesture=False): super(TestTimelinebasedMeasurementPage, self).__init__( 'file://interaction_enabled_page.html', ps, base_dir) self._trigger_animation = trigger_animation self._trigger_jank = trigger_jank self._trigger_slow = trigger_slow + self._trigger_scroll_gesture = trigger_scroll_gesture def RunPageInteractions(self, action_runner): if self._trigger_animation: @@ -31,6 +33,10 @@ if self._trigger_slow: action_runner.TapElement('#slow-button') action_runner.WaitForJavaScriptCondition('window.slowScriptDone') + if self._trigger_scroll_gesture: + interaction = action_runner.BeginGestureInteraction('Scroll') + action_runner.ScrollPage() + interaction.End() class TimelineBasedPageTestTest(page_test_test_case.PageTestTestCase): @@ -88,3 +94,18 @@ v = results.FindAllPageSpecificValuesNamed( 'JankThreadJSRun-responsive-total_big_jank_thread_time') self.assertGreaterEqual(v[0].value, 50) + + def testTimelineBasedMeasurementGestureAdjustmentSmoke(self): + ps = self.CreateEmptyPageSet() + ps.AddUserStory(TestTimelinebasedMeasurementPage( + ps, ps.base_dir, trigger_scroll_gesture=True)) + + tbm = tbm_module.TimelineBasedMeasurement(tbm_module.Options()) + measurement = tbpt_module.TimelineBasedPageTest(tbm) + results = self.RunMeasurement(measurement, ps, + options=self._options) + + self.assertEquals(0, len(results.failures)) + v = results.FindAllPageSpecificValuesNamed( + 'Gesture_Scroll-frame_time_discrepancy') + self.assertEquals(len(v), 1)
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt index 371b4bf..651e1506 100644 --- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt +++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -30,3 +30,5 @@ # http://crbug.com/459000 ClipboardApiTest.HostedAppNoPermission +# http://crbug.com/475172 +BasicExtensionSettingsWebUITest.testUninstall
diff --git a/ui/android/java/src/org/chromium/ui/base/ViewAndroid.java b/ui/android/java/src/org/chromium/ui/base/ViewAndroid.java deleted file mode 100644 index daf0cda1..0000000 --- a/ui/android/java/src/org/chromium/ui/base/ViewAndroid.java +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.ui.base; - -import android.view.View; - -/** - * From the Chromium architecture point of view, ViewAndroid and its native counterpart - * serve purpose of representing Android view where Chrome expects to have a cross platform - * handle to the system view type. As Views are Java object on Android, this ViewAndroid - * and its native counterpart provide the expected abstractions on the C++ side and allow - * it to be flexibly glued to an actual Android Java View at runtime. - * - * It should only be used where access to Android Views is needed from the C++ code. - */ -public class ViewAndroid { - // Native pointer to the c++ ViewAndroid object. - private final ViewAndroidDelegate mViewAndroidDelegate; - private int mKeepScreenOnCount; - private View mKeepScreenOnView; - - /** - * Constructs a View object. - */ - public ViewAndroid(ViewAndroidDelegate viewAndroidDelegate) { - mViewAndroidDelegate = viewAndroidDelegate; - } - - public ViewAndroidDelegate getViewAndroidDelegate() { - return mViewAndroidDelegate; - } - - /** - * Set KeepScreenOn flag. If the flag already set, increase mKeepScreenOnCount. - */ - public void incrementKeepScreenOnCount() { - mKeepScreenOnCount++; - if (mKeepScreenOnCount == 1) { - mKeepScreenOnView = mViewAndroidDelegate.acquireAnchorView(); - mViewAndroidDelegate.setAnchorViewPosition(mKeepScreenOnView, 0, 0, 0, 0); - mKeepScreenOnView.setKeepScreenOn(true); - } - } - - /** - * Decrease mKeepScreenOnCount, if it is decreased to 0, remove the flag. - */ - public void decrementKeepScreenOnCount() { - assert mKeepScreenOnCount > 0; - mKeepScreenOnCount--; - if (mKeepScreenOnCount == 0) { - mViewAndroidDelegate.releaseAnchorView(mKeepScreenOnView); - mKeepScreenOnView = null; - } - } -}
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc index 645d844..45d3d29 100644 --- a/ui/android/view_android.cc +++ b/ui/android/view_android.cc
@@ -5,22 +5,24 @@ #include "ui/android/view_android.h" #include "base/android/jni_android.h" +#include "base/logging.h" namespace ui { using base::android::AttachCurrentThread; using base::android::ScopedJavaLocalRef; -ViewAndroid::ViewAndroid(jobject obj, WindowAndroid* window) +ViewAndroid::ViewAndroid(jobject view_android_delegate, WindowAndroid* window) : window_android_(window) { - java_view_.Reset(AttachCurrentThread(), obj); + DCHECK(view_android_delegate); + view_android_delegate_.Reset(AttachCurrentThread(), view_android_delegate); } ViewAndroid::~ViewAndroid() { } -ScopedJavaLocalRef<jobject> ViewAndroid::GetJavaObject() { - return base::android::ScopedJavaLocalRef<jobject>(java_view_); +ScopedJavaLocalRef<jobject> ViewAndroid::GetViewAndroidDelegate() { + return base::android::ScopedJavaLocalRef<jobject>(view_android_delegate_); } WindowAndroid* ViewAndroid::GetWindowAndroid() {
diff --git a/ui/android/view_android.h b/ui/android/view_android.h index c0d719f..2c70c4ca 100644 --- a/ui/android/view_android.h +++ b/ui/android/view_android.h
@@ -23,10 +23,10 @@ WindowAndroid* GetWindowAndroid(); - base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); + base::android::ScopedJavaLocalRef<jobject> GetViewAndroidDelegate(); private: - base::android::ScopedJavaGlobalRef<jobject> java_view_; + base::android::ScopedJavaGlobalRef<jobject> view_android_delegate_; WindowAndroid* window_android_; DISALLOW_COPY_AND_ASSIGN(ViewAndroid);
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index 0320ef8e..abe3e2e 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn
@@ -103,6 +103,7 @@ "//ui/base/ime", "//ui/compositor", "//ui/events", + "//ui/events:events_base", "//ui/events/platform", "//ui/gfx", "//ui/gfx/geometry",
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 6327dab..ba7f0cc 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -30,7 +30,6 @@ #include "ui/aura/window_tree_host.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" -#include "ui/compositor/paint_context.h" #include "ui/events/event_target_iterator.h" #include "ui/gfx/canvas.h" #include "ui/gfx/path.h"
diff --git a/ui/base/user_activity/user_activity_detector.cc b/ui/base/user_activity/user_activity_detector.cc index d6a4e43..78812bc 100644 --- a/ui/base/user_activity/user_activity_detector.cc +++ b/ui/base/user_activity/user_activity_detector.cc
@@ -8,7 +8,8 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "ui/base/user_activity/user_activity_observer.h" -#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/events/platform/platform_event_source.h" namespace ui { @@ -48,9 +49,24 @@ UserActivityDetector::UserActivityDetector() { CHECK(!g_instance); g_instance = this; + + ui::PlatformEventSource* platform_event_source = + ui::PlatformEventSource::GetInstance(); +#if defined(OS_CHROMEOS) || defined(OS_LINUX) + CHECK(platform_event_source); +#endif + if (platform_event_source) + platform_event_source->AddPlatformEventObserver(this); } UserActivityDetector::~UserActivityDetector() { + ui::PlatformEventSource* platform_event_source = + ui::PlatformEventSource::GetInstance(); +#if defined(OS_CHROMEOS) || defined(OS_LINUX) + CHECK(platform_event_source); +#endif + if (platform_event_source) + platform_event_source->RemovePlatformEventObserver(this); g_instance = nullptr; } @@ -77,36 +93,31 @@ base::TimeDelta::FromMilliseconds(kDisplayPowerChangeIgnoreMouseMs); } -void UserActivityDetector::OnKeyEvent(ui::KeyEvent* event) { - HandleActivity(event); -} - -void UserActivityDetector::OnMouseEvent(ui::MouseEvent* event) { - if (event->flags() & ui::EF_IS_SYNTHESIZED) - return; - if (!honor_mouse_events_time_.is_null() && - GetCurrentTime() < honor_mouse_events_time_) - return; - - HandleActivity(event); -} - -void UserActivityDetector::OnScrollEvent(ui::ScrollEvent* event) { - HandleActivity(event); -} - -void UserActivityDetector::OnTouchEvent(ui::TouchEvent* event) { - HandleActivity(event); -} - -void UserActivityDetector::OnGestureEvent(ui::GestureEvent* event) { - HandleActivity(event); +void UserActivityDetector::DidProcessEvent( + const PlatformEvent& platform_event) { + scoped_ptr<ui::Event> event(ui::EventFromNative(platform_event)); + ProcessReceivedEvent(event.get()); } base::TimeTicks UserActivityDetector::GetCurrentTime() const { return !now_for_test_.is_null() ? now_for_test_ : base::TimeTicks::Now(); } +void UserActivityDetector::ProcessReceivedEvent(const ui::Event* event) { + if (!event) + return; + + if (event->IsMouseEvent() || event->IsMouseWheelEvent()) { + if (event->flags() & ui::EF_IS_SYNTHESIZED) + return; + if (!honor_mouse_events_time_.is_null() + && GetCurrentTime() < honor_mouse_events_time_) + return; + } + + HandleActivity(event); +} + void UserActivityDetector::HandleActivity(const ui::Event* event) { base::TimeTicks now = GetCurrentTime(); last_activity_time_ = now;
diff --git a/ui/base/user_activity/user_activity_detector.h b/ui/base/user_activity/user_activity_detector.h index 4984858..a7665a8 100644 --- a/ui/base/user_activity/user_activity_detector.h +++ b/ui/base/user_activity/user_activity_detector.h
@@ -10,14 +10,15 @@ #include "base/observer_list.h" #include "base/time/time.h" #include "ui/base/ui_base_export.h" -#include "ui/events/event_handler.h" +#include "ui/events/event.h" +#include "ui/events/platform/platform_event_observer.h" namespace ui { class UserActivityObserver; // Watches for input events and notifies observers that the user is active. -class UI_BASE_EXPORT UserActivityDetector : public ui::EventHandler { +class UI_BASE_EXPORT UserActivityDetector : public ui::PlatformEventObserver { public: // Minimum amount of time between notifications to observers. static const int kNotifyIntervalMs; @@ -43,17 +44,19 @@ // Called when displays are about to be turned on or off. void OnDisplayPowerChanging(); - // ui::EventHandler implementation. - void OnKeyEvent(ui::KeyEvent* event) override; - void OnMouseEvent(ui::MouseEvent* event) override; - void OnScrollEvent(ui::ScrollEvent* event) override; - void OnTouchEvent(ui::TouchEvent* event) override; - void OnGestureEvent(ui::GestureEvent* event) override; + // ui::PlatformEventObserver: + void WillProcessEvent(const PlatformEvent& platform_event) override {} + void DidProcessEvent(const PlatformEvent& platform_event) override; private: + friend class UserActivityDetectorTest; + // Returns |now_for_test_| if set or base::TimeTicks::Now() otherwise. base::TimeTicks GetCurrentTime() const; + // Processes the event after it has been converted from a PlatformEvent. + void ProcessReceivedEvent(const ui::Event* event); + // Updates |last_activity_time_|. Additionally notifies observers and // updates |last_observer_notification_time_| if enough time has passed // since the last notification.
diff --git a/ui/base/user_activity/user_activity_detector_unittest.cc b/ui/base/user_activity/user_activity_detector_unittest.cc index dc4cbae..68d9056c 100644 --- a/ui/base/user_activity/user_activity_detector_unittest.cc +++ b/ui/base/user_activity/user_activity_detector_unittest.cc
@@ -13,6 +13,7 @@ #include "ui/events/event_constants.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/events/platform/platform_event_source.h" #include "ui/gfx/geometry/point.h" namespace ui { @@ -36,10 +37,22 @@ DISALLOW_COPY_AND_ASSIGN(TestUserActivityObserver); }; +// A test implementation of PlatformEventSource that we can instantiate to make +// sure that the PlatformEventSource has an instance while in unit tests. +class TestPlatformEventSource : public ui::PlatformEventSource { + public: + TestPlatformEventSource() {} + ~TestPlatformEventSource() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource); +}; + class UserActivityDetectorTest : public testing::Test { public: UserActivityDetectorTest() - : detector_(new UserActivityDetector), + : platform_event_source_(new TestPlatformEventSource), + detector_(new UserActivityDetector), observer_(new TestUserActivityObserver) { detector_->AddObserver(observer_.get()); now_ = base::TimeTicks::Now(); @@ -57,6 +70,11 @@ detector_->set_now_for_test(now_); } + void OnEvent(const ui::Event* event) { + detector_->ProcessReceivedEvent(event); + } + + scoped_ptr<TestPlatformEventSource> platform_event_source_; scoped_ptr<UserActivityDetector> detector_; scoped_ptr<TestUserActivityObserver> observer_; @@ -70,7 +88,7 @@ // events. TEST_F(UserActivityDetectorTest, Basic) { ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - detector_->OnKeyEvent(&key_event); + OnEvent(&key_event); EXPECT_FALSE(key_event.handled()); EXPECT_EQ(now_.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -82,7 +100,7 @@ AdvanceTime(advance_delta); ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - detector_->OnMouseEvent(&mouse_event); + OnEvent(&mouse_event); EXPECT_FALSE(mouse_event.handled()); EXPECT_EQ(now_.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -93,7 +111,7 @@ // Temporarily ignore mouse events when displays are turned on or off. detector_->OnDisplayPowerChanging(); - detector_->OnMouseEvent(&mouse_event); + OnEvent(&mouse_event); EXPECT_FALSE(mouse_event.handled()); EXPECT_EQ(time_before_ignore.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -104,7 +122,7 @@ base::TimeDelta::FromMilliseconds( UserActivityDetector::kDisplayPowerChangeIgnoreMouseMs); AdvanceTime(kIgnoreMouseTime / 2); - detector_->OnMouseEvent(&mouse_event); + OnEvent(&mouse_event); EXPECT_FALSE(mouse_event.handled()); EXPECT_EQ(time_before_ignore.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -113,7 +131,7 @@ // After enough time has passed, mouse events should be reported again. AdvanceTime(std::max(kIgnoreMouseTime, advance_delta)); - detector_->OnMouseEvent(&mouse_event); + OnEvent(&mouse_event); EXPECT_FALSE(mouse_event.handled()); EXPECT_EQ(now_.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -123,7 +141,7 @@ AdvanceTime(advance_delta); ui::TouchEvent touch_event( ui::ET_TOUCH_PRESSED, gfx::Point(), 0, base::TimeDelta()); - detector_->OnTouchEvent(&touch_event); + OnEvent(&touch_event); EXPECT_FALSE(touch_event.handled()); EXPECT_EQ(now_.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -137,7 +155,7 @@ ui::EF_NONE, base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000), ui::GestureEventDetails(ui::ET_GESTURE_TAP)); - detector_->OnGestureEvent(&gesture_event); + OnEvent(&gesture_event); EXPECT_FALSE(gesture_event.handled()); EXPECT_EQ(now_.ToInternalValue(), detector_->last_activity_time().ToInternalValue()); @@ -149,14 +167,14 @@ TEST_F(UserActivityDetectorTest, RateLimitNotifications) { // The observer should be notified about a key event. ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - detector_->OnKeyEvent(&event); + OnEvent(&event); EXPECT_FALSE(event.handled()); EXPECT_EQ(1, observer_->num_invocations()); observer_->reset_stats(); // It shouldn't be notified if a second event occurs in the same instant in // time. - detector_->OnKeyEvent(&event); + OnEvent(&event); EXPECT_FALSE(event.handled()); EXPECT_EQ(0, observer_->num_invocations()); observer_->reset_stats(); @@ -165,7 +183,7 @@ AdvanceTime( base::TimeDelta::FromMilliseconds( UserActivityDetector::kNotifyIntervalMs - 100)); - detector_->OnKeyEvent(&event); + OnEvent(&event); EXPECT_FALSE(event.handled()); EXPECT_EQ(0, observer_->num_invocations()); observer_->reset_stats(); @@ -175,7 +193,7 @@ AdvanceTime(base::TimeDelta::FromMilliseconds( UserActivityDetector::kNotifyIntervalMs)); - detector_->OnKeyEvent(&event); + OnEvent(&event); EXPECT_FALSE(event.handled()); EXPECT_EQ(1, observer_->num_invocations()); } @@ -185,7 +203,7 @@ ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(), ui::EF_IS_SYNTHESIZED, ui::EF_NONE); - detector_->OnMouseEvent(&mouse_event); + OnEvent(&mouse_event); EXPECT_FALSE(mouse_event.handled()); EXPECT_EQ(base::TimeTicks().ToInternalValue(), detector_->last_activity_time().ToInternalValue());
diff --git a/ui/events/event.cc b/ui/events/event.cc index f0804d87..0cdf70d 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -357,6 +357,10 @@ (event2.flags() & ~EF_IS_DOUBLE_CLICK)) return false; + // The new event has been created from the same native event. + if (event1.time_stamp() == event2.time_stamp()) + return false; + base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp(); if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
diff --git a/ui/events/event_unittest.cc b/ui/events/event_unittest.cc index 523cf08..1297f30 100644 --- a/ui/events/event_unittest.cc +++ b/ui/events/event_unittest.cc
@@ -79,6 +79,15 @@ base::TimeDelta soon = start + base::TimeDelta::FromMilliseconds(1); base::TimeDelta later = start + base::TimeDelta::FromMilliseconds(1000); + // Same event. + test_ev1.set_location(gfx::Point(0, 0)); + test_ev2.set_location(gfx::Point(1, 0)); + test_ev1.set_time_stamp(start); + test_ev2.set_time_stamp(start); + EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev2)); + MouseEvent mouse_ev3(mouse_ev1); + EXPECT_FALSE(MouseEvent::IsRepeatedClickEvent(mouse_ev1, mouse_ev3)); + // Close point. test_ev1.set_location(gfx::Point(0, 0)); test_ev2.set_location(gfx::Point(1, 0)); @@ -110,6 +119,7 @@ const gfx::Point origin2(100, 0); scoped_ptr<MouseEvent> ev; base::TimeDelta start = base::TimeDelta::FromMilliseconds(0); + base::TimeDelta soon = start + base::TimeDelta::FromMilliseconds(1); ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin1, origin1, EventTimeForNow(), 0, 0)); @@ -130,11 +140,11 @@ EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev)); ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin2, origin2, EventTimeForNow(), 0, 0)); - ev->set_time_stamp(start); + ev->set_time_stamp(soon); EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev)); ev.reset(new MouseEvent(ET_MOUSE_RELEASED, origin2, origin2, EventTimeForNow(), 0, 0)); - ev->set_time_stamp(start); + ev->set_time_stamp(soon); EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev)); MouseEvent::ResetLastClickForTest(); } @@ -145,6 +155,7 @@ const gfx::Point origin(0, 0); scoped_ptr<MouseEvent> ev; base::TimeDelta start = base::TimeDelta::FromMilliseconds(0); + base::TimeDelta soon = start + base::TimeDelta::FromMilliseconds(1); ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), ui::EF_RIGHT_MOUSE_BUTTON, @@ -161,7 +172,7 @@ EXPECT_EQ(1, MouseEvent::GetRepeatCount(*ev)); ev.reset(new MouseEvent(ET_MOUSE_PRESSED, origin, origin, EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - ev->set_time_stamp(start); + ev->set_time_stamp(soon); EXPECT_EQ(2, MouseEvent::GetRepeatCount(*ev)); MouseEvent::ResetLastClickForTest(); }
diff --git a/ui/events/ozone/evdev/keyboard_evdev.cc b/ui/events/ozone/evdev/keyboard_evdev.cc index 1de30ff8..1d4a5af 100644 --- a/ui/events/ozone/evdev/keyboard_evdev.cc +++ b/ui/events/ozone/evdev/keyboard_evdev.cc
@@ -156,6 +156,7 @@ } void KeyboardEvdev::StopKeyRepeat() { + repeat_key_ = KEY_RESERVED; repeat_sequence_++; }
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc index 8b604ae..770445e2 100644 --- a/ui/events/x/events_x_unittest.cc +++ b/ui/events/x/events_x_unittest.cc
@@ -208,9 +208,11 @@ XEvent event; gfx::Point location(5, 10); + base::TimeDelta time_stamp = base::TimeDelta::FromMilliseconds(1); for (int i = 1; i <= 3; ++i) { InitButtonEvent(&event, true, location, 1, 0); { + event.xbutton.time = time_stamp.InMilliseconds(); MouseEvent mouseev(&event); EXPECT_EQ(ui::ET_MOUSE_PRESSED, mouseev.type()); EXPECT_EQ(i, mouseev.GetClickCount()); @@ -218,10 +220,12 @@ InitButtonEvent(&event, false, location, 1, 0); { + event.xbutton.time = time_stamp.InMilliseconds(); MouseEvent mouseev(&event); EXPECT_EQ(ui::ET_MOUSE_RELEASED, mouseev.type()); EXPECT_EQ(i, mouseev.GetClickCount()); } + time_stamp += base::TimeDelta::FromMilliseconds(1); } }
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index 7201f8ed..79c7837 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -462,14 +462,14 @@ Welcome to the new epic photo importer! </div> <div id="list-container"> - <div id="empty-folder"> + <div id="empty-folder" hidden> <div class="image"></div> <span class="label" i18n-content="EMPTY_FOLDER"></span> </div> <div class="detail-table" id="detail-table" tabindex="1" autofocus> </div> <grid class="thumbnail-grid" tabindex="2"></grid> - <paper-progress class="loading-indicator" indeterminate></paper-progress> + <paper-progress class="loading-indicator" indeterminate hidden></paper-progress> <div class="drive-welcome page"></div> <div id="no-search-results"></div> </div>
diff --git a/ui/file_manager/integration_tests/file_manager/file_display.js b/ui/file_manager/integration_tests/file_manager/file_display.js index 54f9e48..d122daf 100644 --- a/ui/file_manager/integration_tests/file_manager/file_display.js +++ b/ui/file_manager/integration_tests/file_manager/file_display.js
@@ -88,3 +88,111 @@ } ]); }; + +/** + * Searches for a string in Downloads and checks the correct results are + * being displayed. + * + * @param {string} searchTerm The string to search for. + * @param {Array<Object>} expectedResults The results set. + * + */ +function searchDownloads(searchTerm, expectedResults) { + var appId; + + StepsRunner.run([ + function() { + setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next); + }, + // Focus the search box. + function(inAppId, list) { + appId = inAppId; + remoteCall.callRemoteTestUtil('fakeEvent', + appId, + ['#search-box input', 'focus'], + this.next); + }, + // Input a text. + function(result) { + chrome.test.assertTrue(result); + remoteCall.callRemoteTestUtil('inputText', + appId, + ['#search-box input', searchTerm], + this.next); + }, + // Notify the element of the input. + function() { + remoteCall.callRemoteTestUtil('fakeEvent', + appId, + ['#search-box input', 'input'], + this.next); + }, + function(result) { + remoteCall.waitForFileListChange(appId, BASIC_LOCAL_ENTRY_SET.length). + then(this.next); + }, + function(actualFilesAfter) { + chrome.test.assertEq( + TestEntryInfo.getExpectedRows(expectedResults).sort(), + actualFilesAfter); + + checkIfNoErrorsOccured(this.next); + } + ]); +} + +testcase.searchNormal = function() { + searchDownloads('hello', [ENTRIES.hello]); +}; + +testcase.searchCaseInsensitive = function() { + searchDownloads('HELLO', [ENTRIES.hello]); +}; + +/** + * Searches for a string that doesn't match anything in Downloads + * and checks that the no items match string is displayed. + * + */ +testcase.searchNotFound = function() { + var appId; + var searchTerm = 'blahblah'; + + StepsRunner.run([ + function() { + setupAndWaitUntilReady(null, RootPath.DOWNLOADS, this.next); + }, + // Focus the search box. + function(inAppId, list) { + appId = inAppId; + console.log(list); + remoteCall.callRemoteTestUtil('fakeEvent', + appId, + ['#search-box input', 'focus'], + this.next); + }, + // Input a text. + function(result) { + chrome.test.assertTrue(result); + remoteCall.callRemoteTestUtil('inputText', + appId, + ['#search-box input', searchTerm], + this.next); + }, + // Notify the element of the input. + function() { + remoteCall.callRemoteTestUtil('fakeEvent', + appId, + ['#search-box input', 'input'], + this.next); + }, + function(result) { + remoteCall.waitForElement(appId, ['#no-search-results b']). + then(this.next); + }, + function(element) { + chrome.test.assertEq(element.text, '\"' + searchTerm + '\"'); + checkIfNoErrorsOccured(this.next); + } + ]); +};
diff --git a/ui/gfx/display_change_notifier_unittest.cc b/ui/gfx/display_change_notifier_unittest.cc index 47b5bd06..9c1dda2 100644 --- a/ui/gfx/display_change_notifier_unittest.cc +++ b/ui/gfx/display_change_notifier_unittest.cc
@@ -70,13 +70,6 @@ EXPECT_EQ(1, observer.display_added()); } -TEST(DisplayChangeNotifierTest, AddObserver_Null) { - DisplayChangeNotifier change_notifier; - - change_notifier.AddObserver(NULL); - // Should not crash. -} - TEST(DisplayChangeNotifier, RemoveObserver_Smoke) { DisplayChangeNotifier change_notifier; MockDisplayObserver observer; @@ -93,13 +86,6 @@ EXPECT_EQ(0, observer.display_added()); } -TEST(DisplayChangeNotifierTest, RemoveObserver_Null) { - DisplayChangeNotifier change_notifier; - - change_notifier.RemoveObserver(NULL); - // Should not crash. -} - TEST(DisplayChangeNotifierTest, RemoveObserver_Unknown) { DisplayChangeNotifier change_notifier; MockDisplayObserver observer;
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index 6383a138..5b1d47e 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h
@@ -48,6 +48,7 @@ DXT1, DXT5, ETC1, + R_8, RGBA_8888, RGBX_8888, BGRA_8888,
diff --git a/ui/gl/angle_platform_impl.cc b/ui/gl/angle_platform_impl.cc index 2ce12b8..47f6cef 100644 --- a/ui/gl/angle_platform_impl.cc +++ b/ui/gl/angle_platform_impl.cc
@@ -6,6 +6,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" +#include "base/trace_event/trace_event.h" namespace gfx { @@ -15,6 +16,49 @@ ANGLEPlatformImpl::~ANGLEPlatformImpl() { } +double ANGLEPlatformImpl::monotonicallyIncreasingTime() { + return base::TimeTicks::Now().ToInternalValue() / + static_cast<double>(base::Time::kMicrosecondsPerSecond); +} + +const unsigned char* ANGLEPlatformImpl::getTraceCategoryEnabledFlag( + const char* category_group) { + return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); +} + +angle::Platform::TraceEventHandle ANGLEPlatformImpl::addTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + double timestamp, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + unsigned char flags) { + base::TimeTicks timestamp_tt = base::TimeTicks::FromInternalValue( + static_cast<int64>(timestamp * base::Time::kMicrosecondsPerSecond)); + base::trace_event::TraceEventHandle handle = + TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, id, + base::PlatformThread::CurrentId(), timestamp_tt, num_args, arg_names, + arg_types, arg_values, nullptr, flags); + angle::Platform::TraceEventHandle result; + memcpy(&result, &handle, sizeof(result)); + return result; +} + +void ANGLEPlatformImpl::updateTraceEventDuration( + const unsigned char* category_group_enabled, + const char* name, + TraceEventHandle handle) { + base::trace_event::TraceEventHandle trace_event_handle; + memcpy(&trace_event_handle, &handle, sizeof(handle)); + TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled, name, + trace_event_handle); +} + void ANGLEPlatformImpl::histogramCustomCounts(const char* name, int sample, int min,
diff --git a/ui/gl/angle_platform_impl.h b/ui/gl/angle_platform_impl.h index 2d12f60..92d1397f 100644 --- a/ui/gl/angle_platform_impl.h +++ b/ui/gl/angle_platform_impl.h
@@ -20,6 +20,22 @@ ~ANGLEPlatformImpl() override; // angle::Platform: + double monotonicallyIncreasingTime() override; + const unsigned char* getTraceCategoryEnabledFlag( + const char* category_group) override; + TraceEventHandle addTraceEvent(char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + double timestamp, + int num_args, + const char** arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + unsigned char flags) override; + void updateTraceEventDuration(const unsigned char* category_group_enabled, + const char* name, + TraceEventHandle handle) override; void histogramCustomCounts(const char* name, int sample, int min,
diff --git a/ui/gl/gl_image_egl.cc b/ui/gl/gl_image_egl.cc index c0a404c..df4ce31 100644 --- a/ui/gl/gl_image_egl.cc +++ b/ui/gl/gl_image_egl.cc
@@ -14,12 +14,14 @@ } GLImageEGL::~GLImageEGL() { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); } bool GLImageEGL::Initialize(EGLenum target, EGLClientBuffer buffer, const EGLint* attrs) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_); egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(), EGL_NO_CONTEXT, @@ -35,6 +37,7 @@ } void GLImageEGL::Destroy(bool have_context) { + DCHECK(thread_checker_.CalledOnValidThread()); if (egl_image_ != EGL_NO_IMAGE_KHR) { EGLBoolean result = eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_); @@ -49,6 +52,7 @@ gfx::Size GLImageEGL::GetSize() { return size_; } bool GLImageEGL::BindTexImage(unsigned target) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); glEGLImageTargetTexture2DOES(target, egl_image_); DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
diff --git a/ui/gl/gl_image_egl.h b/ui/gl/gl_image_egl.h index 716761f..a4abd24 100644 --- a/ui/gl/gl_image_egl.h +++ b/ui/gl/gl_image_egl.h
@@ -5,6 +5,7 @@ #ifndef UI_GL_GL_IMAGE_EGL_H_ #define UI_GL_GL_IMAGE_EGL_H_ +#include "base/threading/thread_checker.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_image.h" @@ -37,6 +38,7 @@ EGLImageKHR egl_image_; const gfx::Size size_; + base::ThreadChecker thread_checker_; private: DISALLOW_COPY_AND_ASSIGN(GLImageEGL);
diff --git a/ui/gl/gl_image_io_surface.cc b/ui/gl/gl_image_io_surface.cc index 9d27a29..2bb328b 100644 --- a/ui/gl/gl_image_io_surface.cc +++ b/ui/gl/gl_image_io_surface.cc
@@ -16,22 +16,26 @@ } GLImageIOSurface::~GLImageIOSurface() { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!io_surface_); } bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!io_surface_); io_surface_.reset(io_surface); return true; } void GLImageIOSurface::Destroy(bool have_context) { + DCHECK(thread_checker_.CalledOnValidThread()); io_surface_.reset(); } gfx::Size GLImageIOSurface::GetSize() { return size_; } bool GLImageIOSurface::BindTexImage(unsigned target) { + DCHECK(thread_checker_.CalledOnValidThread()); if (target != GL_TEXTURE_RECTANGLE_ARB) { // This might be supported in the future. For now, perform strict // validation so we know what's going on.
diff --git a/ui/gl/gl_image_io_surface.h b/ui/gl/gl_image_io_surface.h index 8497278..4ec8555 100644 --- a/ui/gl/gl_image_io_surface.h +++ b/ui/gl/gl_image_io_surface.h
@@ -8,6 +8,7 @@ #include <IOSurface/IOSurfaceAPI.h> #include "base/mac/scoped_cftyperef.h" +#include "base/threading/thread_checker.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gl/gl_image.h" @@ -41,6 +42,7 @@ private: base::ScopedCFTypeRef<IOSurfaceRef> io_surface_; const gfx::Size size_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(GLImageIOSurface); };
diff --git a/ui/gl/gl_image_linux_dma_buffer.cc b/ui/gl/gl_image_linux_dma_buffer.cc index 080c9b5..ff18f8f 100644 --- a/ui/gl/gl_image_linux_dma_buffer.cc +++ b/ui/gl/gl_image_linux_dma_buffer.cc
@@ -37,6 +37,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: case gfx::GpuMemoryBuffer::YUV_420: @@ -53,6 +54,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::YUV_420: @@ -60,6 +62,8 @@ } NOTREACHED(); return false; + case GL_R8: + return false; default: return false; } @@ -76,6 +80,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::YUV_420: NOTREACHED();
diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc index ff9c97ee..908ce7e 100644 --- a/ui/gl/gl_image_memory.cc +++ b/ui/gl/gl_image_memory.cc
@@ -19,6 +19,7 @@ bool ValidInternalFormat(unsigned internalformat) { switch (internalformat) { + case GL_R8: case GL_RGBA: case GL_BGRA_EXT: return true; @@ -34,6 +35,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: return true; @@ -55,6 +57,7 @@ case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::YUV_420: return true; + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: case gfx::GpuMemoryBuffer::RGBX_8888: @@ -77,6 +80,8 @@ return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; case gfx::GpuMemoryBuffer::ETC1: return GL_ETC1_RGB8_OES; + case gfx::GpuMemoryBuffer::R_8: + return GL_RED; case gfx::GpuMemoryBuffer::RGBA_8888: return GL_RGBA; case gfx::GpuMemoryBuffer::BGRA_8888: @@ -99,6 +104,7 @@ switch (format) { case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: + case gfx::GpuMemoryBuffer::R_8: return GL_UNSIGNED_BYTE; case gfx::GpuMemoryBuffer::ATC: case gfx::GpuMemoryBuffer::ATCIA: @@ -155,27 +161,30 @@ bool GLImageMemory::StrideInBytes(size_t width, gfx::GpuMemoryBuffer::Format format, size_t* stride_in_bytes) { - base::CheckedNumeric<size_t> s = width; + base::CheckedNumeric<size_t> checked_stride = width; switch (format) { - case gfx::GpuMemoryBuffer::ATC: - case gfx::GpuMemoryBuffer::DXT1: - case gfx::GpuMemoryBuffer::ETC1: - DCHECK_EQ(width % 2, 0U); - s /= 2; - if (!s.IsValid()) - return false; - *stride_in_bytes = s.ValueOrDie(); - return true; case gfx::GpuMemoryBuffer::ATCIA: case gfx::GpuMemoryBuffer::DXT5: *stride_in_bytes = width; return true; + case gfx::GpuMemoryBuffer::ATC: + case gfx::GpuMemoryBuffer::DXT1: + case gfx::GpuMemoryBuffer::ETC1: + DCHECK_EQ(width % 2, 0u); + *stride_in_bytes = width / 2; + return true; + case gfx::GpuMemoryBuffer::R_8: + checked_stride += 3; + if (!checked_stride.IsValid()) + return false; + *stride_in_bytes = checked_stride.ValueOrDie() & ~0x3; + return true; case gfx::GpuMemoryBuffer::RGBA_8888: case gfx::GpuMemoryBuffer::BGRA_8888: - s *= 4; - if (!s.IsValid()) + checked_stride *= 4; + if (!checked_stride.IsValid()) return false; - *stride_in_bytes = s.ValueOrDie(); + *stride_in_bytes = checked_stride.ValueOrDie(); return true; case gfx::GpuMemoryBuffer::RGBX_8888: case gfx::GpuMemoryBuffer::YUV_420: @@ -358,8 +367,7 @@ 0, // y-offset size_.width(), size_.height(), DataFormat(format_), - SizeInBytes(size_, format_), - memory_); + SizeInBytes(size_, format_), memory_); } else { glTexSubImage2D(GL_TEXTURE_2D, 0, // mip level
diff --git a/ui/gl/gl_image_surface_texture.cc b/ui/gl/gl_image_surface_texture.cc index a321c4d3..20e7b156 100644 --- a/ui/gl/gl_image_surface_texture.cc +++ b/ui/gl/gl_image_surface_texture.cc
@@ -14,17 +14,20 @@ } GLImageSurfaceTexture::~GLImageSurfaceTexture() { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!surface_texture_.get()); DCHECK_EQ(0, texture_id_); } bool GLImageSurfaceTexture::Initialize(SurfaceTexture* surface_texture) { + DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!surface_texture_.get()); surface_texture_ = surface_texture; return true; } void GLImageSurfaceTexture::Destroy(bool have_context) { + DCHECK(thread_checker_.CalledOnValidThread()); surface_texture_ = NULL; texture_id_ = 0; } @@ -33,6 +36,7 @@ bool GLImageSurfaceTexture::BindTexImage(unsigned target) { TRACE_EVENT0("gpu", "GLImageSurfaceTexture::BindTexImage"); + DCHECK(thread_checker_.CalledOnValidThread()); if (target != GL_TEXTURE_EXTERNAL_OES) { LOG(ERROR)
diff --git a/ui/gl/gl_image_surface_texture.h b/ui/gl/gl_image_surface_texture.h index d2ff5b70..b4d57b0 100644 --- a/ui/gl/gl_image_surface_texture.h +++ b/ui/gl/gl_image_surface_texture.h
@@ -6,6 +6,7 @@ #define UI_GL_GL_IMAGE_SURFACE_TEXTURE_H_ #include "base/memory/ref_counted.h" +#include "base/threading/thread_checker.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_image.h" @@ -41,6 +42,7 @@ scoped_refptr<SurfaceTexture> surface_texture_; const gfx::Size size_; GLint texture_id_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(GLImageSurfaceTexture); };
diff --git a/ui/gl/gl_implementation_win.cc b/ui/gl/gl_implementation_win.cc index 49ffa89..40cbdde 100644 --- a/ui/gl/gl_implementation_win.cc +++ b/ui/gl/gl_implementation_win.cc
@@ -61,45 +61,6 @@ return true; } -const unsigned char* AngleGetTraceCategoryEnabledFlag(const char* name) { - return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name); -} - -void AngleAddTraceEvent(char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int num_args, - const char** arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - unsigned char flags) { - TRACE_EVENT_API_ADD_TRACE_EVENT(phase, - category_group_enabled, - name, - id, - num_args, - arg_names, - arg_types, - arg_values, - NULL, - flags); -} - -typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); -typedef void (*AddTraceEventFunc)(char phase, - const unsigned char* categoryGroupEnabled, - const char* name, - unsigned long long id, - int numArgs, - const char** argNames, - const unsigned char* argTypes, - const unsigned long long* argValues, - unsigned char flags); -typedef void (__stdcall *SetTraceFunctionPointersFunc)( - GetCategoryEnabledFlagFunc get_category_enabled_flag, - AddTraceEventFunc add_trace_event_func); - // TODO(jmadill): Apply to all platforms eventually base::LazyInstance<ANGLEPlatformImpl> g_angle_platform_impl = LAZY_INSTANCE_INITIALIZER; @@ -213,16 +174,6 @@ #endif if (!using_swift_shader) { - // TODO(jmadill): remove when platform impl supports tracing - SetTraceFunctionPointersFunc set_trace_function_pointers = - reinterpret_cast<SetTraceFunctionPointersFunc>( - base::GetFunctionPointerFromNativeLibrary( - gles_library, "SetTraceFunctionPointers")); - if (set_trace_function_pointers) { - set_trace_function_pointers(&AngleGetTraceCategoryEnabledFlag, - &AngleAddTraceEvent); - } - // Init ANGLE platform here, before we call GetPlatformDisplay(). // TODO(jmadill): Apply to all platforms eventually ANGLEPlatformInitializeFunc angle_platform_init =
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn index 66a98a4..28f34f13 100644 --- a/ui/keyboard/BUILD.gn +++ b/ui/keyboard/BUILD.gn
@@ -35,6 +35,7 @@ "//base/third_party/dynamic_annotations", "//content/public/browser", "//content/public/common", + "//ipc", "//skia", "//ui/aura", "//ui/base",
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index 3365610f..5aa44bb 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -48,41 +48,13 @@ // allowed to be shown with zero opacity, we always animate to 0.01 instead. const float kAnimationStartOrAfterHideOpacity = 0.01f; -// Event targeter for the keyboard container. -class KeyboardContainerTargeter : public wm::MaskedWindowTargeter { - public: - KeyboardContainerTargeter(aura::Window* container, - keyboard::KeyboardControllerProxy* proxy) - : wm::MaskedWindowTargeter(container), - proxy_(proxy) { - } - - ~KeyboardContainerTargeter() override {} - - private: - // wm::MaskedWindowTargeter: - bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override { - if (proxy_ && !proxy_->HasKeyboardWindow()) - return true; - gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() : - keyboard::DefaultKeyboardBoundsFromWindowBounds(window->bounds()); - mask->addRect(RectToSkRect(keyboard_bounds)); - return true; - } - - keyboard::KeyboardControllerProxy* proxy_; - - DISALLOW_COPY_AND_ASSIGN(KeyboardContainerTargeter); -}; - // The KeyboardWindowDelegate makes sure the keyboard-window does not get focus. // This is necessary to make sure that the synthetic key-events reach the target // window. // The delegate deletes itself when the window is destroyed. class KeyboardWindowDelegate : public aura::WindowDelegate { public: - explicit KeyboardWindowDelegate(keyboard::KeyboardControllerProxy* proxy) - : proxy_(proxy) {} + KeyboardWindowDelegate() {} ~KeyboardWindowDelegate() override {} private: @@ -90,9 +62,7 @@ gfx::Size GetMinimumSize() const override { return gfx::Size(); } gfx::Size GetMaximumSize() const override { return gfx::Size(); } void OnBoundsChanged(const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) override { - bounds_ = new_bounds; - } + const gfx::Rect& new_bounds) override {} ui::TextInputClient* GetFocusedTextInputClient() override { return nullptr; } @@ -114,19 +84,8 @@ void OnWindowDestroying(aura::Window* window) override {} void OnWindowDestroyed(aura::Window* window) override { delete this; } void OnWindowTargetVisibilityChanged(bool visible) override {} - bool HasHitTestMask() const override { - return !proxy_ || proxy_->HasKeyboardWindow(); - } - void GetHitTestMask(gfx::Path* mask) const override { - if (proxy_ && !proxy_->HasKeyboardWindow()) - return; - gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() : - keyboard::DefaultKeyboardBoundsFromWindowBounds(bounds_); - mask->addRect(RectToSkRect(keyboard_bounds)); - } - - gfx::Rect bounds_; - keyboard::KeyboardControllerProxy* proxy_; + bool HasHitTestMask() const override { return false; } + void GetHitTestMask(gfx::Path* mask) const override {} DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate); }; @@ -254,8 +213,11 @@ } KeyboardController::~KeyboardController() { - if (container_) + if (container_) { + if (container_->GetRootWindow()) + container_->GetRootWindow()->RemoveObserver(this); container_->RemoveObserver(this); + } if (input_method_) input_method_->RemoveObserver(this); ResetWindowInsets(); @@ -275,10 +237,7 @@ aura::Window* KeyboardController::GetContainerWindow() { if (!container_.get()) { - container_.reset(new aura::Window( - new KeyboardWindowDelegate(proxy_.get()))); - container_->SetEventTargeter(scoped_ptr<ui::EventTargeter>( - new KeyboardContainerTargeter(container_.get(), proxy_.get()))); + container_.reset(new aura::Window(new KeyboardWindowDelegate())); container_->SetName("KeyboardContainer"); container_->set_owned_by_parent(false); container_->Init(ui::LAYER_NOT_DRAWN); @@ -388,6 +347,45 @@ OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient()); } +void KeyboardController::OnWindowAddedToRootWindow(aura::Window* window) { + if (!window->GetRootWindow()->HasObserver(this)) + window->GetRootWindow()->AddObserver(this); +} + +void KeyboardController::OnWindowRemovingFromRootWindow(aura::Window* window, + aura::Window* new_root) { + if (window->GetRootWindow()->HasObserver(this)) + window->GetRootWindow()->RemoveObserver(this); +} + +void KeyboardController::OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + if (!window->IsRootWindow()) + return; + // Keep the same height when window resize. It gets called when screen + // rotate. + if (!keyboard_container_initialized() || !proxy_->HasKeyboardWindow()) + return; + + int container_height = container_->bounds().height(); + if (keyboard_mode_ == FULL_WIDTH) { + container_->SetBounds(gfx::Rect(new_bounds.x(), + new_bounds.bottom() - container_height, + new_bounds.width(), + container_height)); + } else if (keyboard_mode_ == FLOATING) { + // When screen rotate, horizontally center floating virtual keyboard + // window and vertically align it to the bottom. + int container_width = container_->bounds().width(); + container_->SetBounds(gfx::Rect( + new_bounds.x() + (new_bounds.width() - container_width) / 2, + new_bounds.bottom() - container_height, + container_width, + container_height)); + } +} + void KeyboardController::Reload() { if (proxy_->HasKeyboardWindow()) { // A reload should never try to show virtual keyboard. If keyboard is not @@ -441,15 +439,14 @@ } bool KeyboardController::ShouldEnableInsets(aura::Window* window) { - aura::Window *keyboard_window = proxy_->GetKeyboardWindow(); + aura::Window* keyboard_window = proxy_->GetKeyboardWindow(); return (keyboard_window->GetRootWindow() == window->GetRootWindow() && keyboard::IsKeyboardOverscrollEnabled() && - proxy_->GetKeyboardWindow()->IsVisible() && - keyboard_visible_); + keyboard_window->IsVisible() && keyboard_visible_); } void KeyboardController::UpdateWindowInsets(aura::Window* window) { - aura::Window *keyboard_window = proxy_->GetKeyboardWindow(); + aura::Window* keyboard_window = proxy_->GetKeyboardWindow(); if (window == keyboard_window) return; @@ -459,8 +456,8 @@ content::RenderWidgetHostView* view = widget->GetView(); if (view && window->Contains(view->GetNativeView())) { gfx::Rect window_bounds = view->GetNativeView()->GetBoundsInScreen(); - gfx::Rect intersect = gfx::IntersectRects(window_bounds, - proxy_->GetKeyboardWindow()->bounds()); + gfx::Rect intersect = + gfx::IntersectRects(window_bounds, keyboard_window->bounds()); int overlap = ShouldEnableInsets(window) ? intersect.height() : 0; if (overlap > 0 && overlap < window_bounds.height()) view->SetInsets(gfx::Insets(0, 0, overlap, 0)); @@ -564,7 +561,7 @@ void KeyboardController::ShowAnimationFinished() { // Notify observers after animation finished to prevent reveal desktop // background during animation. - NotifyKeyboardBoundsChanging(proxy_->GetKeyboardWindow()->bounds()); + NotifyKeyboardBoundsChanging(container_->bounds()); proxy_->EnsureCaretInWorkArea(); }
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h index d81beda..53da81a 100644 --- a/ui/keyboard/keyboard_controller.h +++ b/ui/keyboard/keyboard_controller.h
@@ -92,6 +92,8 @@ void set_lock_keyboard(bool lock) { lock_keyboard_ = lock; } + KeyboardMode keyboard_mode() const { return keyboard_mode_; } + void SetKeyboardMode(KeyboardMode mode); // Force the keyboard to show up if not showing and lock the keyboard if @@ -129,6 +131,12 @@ // aura::WindowObserver overrides void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override; + void OnWindowAddedToRootWindow(aura::Window* window) override; + void OnWindowRemovingFromRootWindow(aura::Window* window, + aura::Window* new_root) override; + void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) override; // InputMethodObserver overrides void OnTextInputTypeChanged(const ui::TextInputClient* client) override {}
diff --git a/ui/keyboard/keyboard_controller_proxy.cc b/ui/keyboard/keyboard_controller_proxy.cc index bf921ef..83d5e774 100644 --- a/ui/keyboard/keyboard_controller_proxy.cc +++ b/ui/keyboard/keyboard_controller_proxy.cc
@@ -55,15 +55,10 @@ // point. Otherwise, wrong keyboard bounds is used and may cause problem as // described in crbug.com/367788. DCHECK(keyboard->parent()); - gfx::Rect bounds = keyboard->bounds(); - int new_height = pos.height(); - bounds.set_y(bounds.y() + bounds.height() - new_height); - bounds.set_height(new_height); - // Keyboard bounds should only be reset when it actually changes. Otherwise - // it interrupts the initial animation of showing the keyboard. Described in - // crbug.com/356753. - if (bounds != keyboard->bounds()) - keyboard->SetBounds(bounds); + // keyboard window bounds may not set to |pos| after this call. If keyboard + // is in FULL_WIDTH mode, only the height of keyboard window will be + // changed. + keyboard->SetBounds(pos); } // Overridden from content::WebContentsDelegate:
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc index 38094ceb..52d7608 100644 --- a/ui/keyboard/keyboard_controller_unittest.cc +++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -37,6 +37,13 @@ namespace keyboard { namespace { +// Verify if the |keyboard| window covers the |container| window completely. +void VerifyKeyboardWindowSize(aura::Window* container, aura::Window* keyboard) { + ASSERT_EQ(gfx::Rect(0, 0, container->bounds().width(), + container->bounds().height()), + keyboard->bounds()); +} + // Steps a layer animation until it is completed. Animations must be enabled. void RunAnimationForLayer(ui::Layer* layer) { // Animations must be enabled for stepping to work. @@ -201,6 +208,15 @@ SetFocus(test_text_input_client_.get()); } + void MockRotateScreen() { + const gfx::Rect root_bounds = root_window()->bounds(); + controller_->OnWindowBoundsChanged(root_window(), gfx::Rect(), + gfx::Rect(0, + 0, + root_bounds.height(), + root_bounds.width())); + } + protected: void SetFocus(ui::TextInputClient* client) { ui::InputMethod* input_method = proxy()->GetInputMethod(); @@ -215,8 +231,8 @@ if (proxy_->GetKeyboardWindow()->bounds().height() == 0) { // Set initial bounds for test keyboard window. proxy_->GetKeyboardWindow()->SetBounds( - KeyboardBoundsFromWindowBounds( - controller()->GetContainerWindow()->bounds(), 100)); + FullWidthKeyboardBoundsFromRootBounds(root_window()->bounds(), + 100)); } } } @@ -243,26 +259,50 @@ TEST_F(KeyboardControllerTest, KeyboardSize) { aura::Window* container(controller()->GetContainerWindow()); aura::Window* keyboard(proxy()->GetKeyboardWindow()); - container->SetBounds(gfx::Rect(0, 0, 200, 100)); - + gfx::Rect screen_bounds = root_window()->bounds(); + root_window()->AddChild(container); container->AddChild(keyboard); - const gfx::Rect& before_bounds = keyboard->bounds(); - // The initial keyboard should be positioned at the bottom of container and - // has 0 height. - ASSERT_EQ(gfx::Rect(0, 100, 200, 0), before_bounds); + const gfx::Rect& initial_bounds = container->bounds(); + // The container should be positioned at the bottom of screen and has 0 + // height. + ASSERT_EQ(gfx::Rect(), initial_bounds); + VerifyKeyboardWindowSize(container, keyboard); - gfx::Rect new_bounds( - before_bounds.x(), before_bounds.y() - 50, - before_bounds.width(), 50); + gfx::Rect new_bounds(0, 0, 50, 50); + + // In FULL_WIDTH mode, attempt to change window width or move window up from + // the bottom are ignored. Changing window height is supported. + gfx::Rect expected_bounds(0, + screen_bounds.height() - 50, + screen_bounds.width(), + 50); keyboard->SetBounds(new_bounds); - ASSERT_EQ(new_bounds, keyboard->bounds()); + ASSERT_EQ(expected_bounds, container->bounds()); + VerifyKeyboardWindowSize(container, keyboard); - // Mock a screen rotation. - container->SetBounds(gfx::Rect(0, 0, 100, 200)); + MockRotateScreen(); // The above call should resize keyboard to new width while keeping the old // height. - ASSERT_EQ(gfx::Rect(0, 150, 100, 50), keyboard->bounds()); + ASSERT_EQ(gfx::Rect(0, + screen_bounds.width() - 50, + screen_bounds.height(), + 50), + container->bounds()); + VerifyKeyboardWindowSize(container, keyboard); +} + +TEST_F(KeyboardControllerTest, FloatingKeyboardSize) { + aura::Window* container(controller()->GetContainerWindow()); + aura::Window* keyboard(proxy()->GetKeyboardWindow()); + gfx::Rect screen_bounds = root_window()->bounds(); + root_window()->AddChild(container); + controller()->SetKeyboardMode(FLOATING); + container->AddChild(keyboard); + gfx::Rect new_bounds(0, 50, 50, 50); + keyboard->SetBounds(new_bounds); + ASSERT_EQ(new_bounds, container->bounds()); + VerifyKeyboardWindowSize(container, keyboard); } // Tests that tapping/clicking inside the keyboard does not give it focus. @@ -277,7 +317,6 @@ window->Focus(); aura::Window* keyboard_container(controller()->GetContainerWindow()); - keyboard_container->SetBounds(root_bounds); root_window()->AddChild(keyboard_container); keyboard_container->Show(); @@ -295,7 +334,7 @@ keyboard_container->AddPreTargetHandler(&observer); ui::test::EventGenerator generator(root_window()); - generator.MoveMouseTo(proxy()->GetKeyboardWindow()->bounds().CenterPoint()); + generator.MoveMouseTo(keyboard_container->bounds().CenterPoint()); generator.ClickLeftButton(); EXPECT_TRUE(window->HasFocus()); EXPECT_FALSE(keyboard_container->HasFocus()); @@ -310,80 +349,7 @@ keyboard_container->RemovePreTargetHandler(&observer); } -TEST_F(KeyboardControllerTest, EventHitTestingInContainer) { - const gfx::Rect& root_bounds = root_window()->bounds(); - aura::test::EventCountDelegate delegate; - scoped_ptr<aura::Window> window(new aura::Window(&delegate)); - window->Init(ui::LAYER_NOT_DRAWN); - window->SetBounds(root_bounds); - root_window()->AddChild(window.get()); - window->Show(); - window->Focus(); - - aura::Window* keyboard_container(controller()->GetContainerWindow()); - keyboard_container->SetBounds(root_bounds); - - root_window()->AddChild(keyboard_container); - keyboard_container->Show(); - - ShowKeyboard(); - - EXPECT_TRUE(window->IsVisible()); - EXPECT_TRUE(keyboard_container->IsVisible()); - EXPECT_TRUE(window->HasFocus()); - EXPECT_FALSE(keyboard_container->HasFocus()); - - // Make sure hit testing works correctly while the keyboard is visible. - aura::Window* keyboard_window = proxy()->GetKeyboardWindow(); - ui::EventTarget* root = root_window(); - ui::EventTargeter* targeter = root->GetEventTargeter(); - gfx::Point location = keyboard_window->bounds().CenterPoint(); - ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, location, location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - EXPECT_EQ(keyboard_window, targeter->FindTargetForEvent(root, &mouse1)); - - location.set_y(keyboard_window->bounds().y() - 5); - ui::MouseEvent mouse2(ui::ET_MOUSE_MOVED, location, location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse2)); -} - -TEST_F(KeyboardControllerTest, KeyboardWindowCreation) { - const gfx::Rect& root_bounds = root_window()->bounds(); - aura::test::EventCountDelegate delegate; - scoped_ptr<aura::Window> window(new aura::Window(&delegate)); - window->Init(ui::LAYER_NOT_DRAWN); - window->SetBounds(root_bounds); - root_window()->AddChild(window.get()); - window->Show(); - window->Focus(); - - aura::Window* keyboard_container(controller()->GetContainerWindow()); - keyboard_container->SetBounds(root_bounds); - - root_window()->AddChild(keyboard_container); - keyboard_container->Show(); - - EXPECT_FALSE(proxy()->HasKeyboardWindow()); - - ui::EventTarget* root = root_window(); - ui::EventTargeter* targeter = root->GetEventTargeter(); - gfx::Point location(root_window()->bounds().width() / 2, - root_window()->bounds().height() - 10); - ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); - EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root, &mouse)); - EXPECT_FALSE(proxy()->HasKeyboardWindow()); - - EXPECT_EQ( - controller()->GetContainerWindow(), - controller()->GetContainerWindow()->GetEventHandlerForPoint(location)); - EXPECT_FALSE(proxy()->HasKeyboardWindow()); -} - TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) { - const gfx::Rect& root_bounds = root_window()->bounds(); - ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); ui::DummyTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT); @@ -393,7 +359,6 @@ aura::Window* keyboard_container(controller()->GetContainerWindow()); scoped_ptr<KeyboardContainerObserver> keyboard_container_observer( new KeyboardContainerObserver(keyboard_container)); - keyboard_container->SetBounds(root_bounds); root_window()->AddChild(keyboard_container); SetFocus(&input_client_0); @@ -425,13 +390,10 @@ // Test to prevent spurious overscroll boxes when changing tabs during keyboard // hide. Refer to crbug.com/401670 for more context. TEST_F(KeyboardControllerTest, CheckOverscrollInsetDuringVisibilityChange) { - const gfx::Rect& root_bounds = root_window()->bounds(); - ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT); ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE); aura::Window* keyboard_container(controller()->GetContainerWindow()); - keyboard_container->SetBounds(root_bounds); root_window()->AddChild(keyboard_container); // Enable touch keyboard / overscroll mode to test insets. @@ -450,8 +412,6 @@ } TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) { - const gfx::Rect& root_bounds = root_window()->bounds(); - ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT); ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT); ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE); @@ -460,7 +420,6 @@ aura::Window* keyboard_container(controller()->GetContainerWindow()); scoped_ptr<KeyboardContainerObserver> keyboard_container_observer( new KeyboardContainerObserver(keyboard_container)); - keyboard_container->SetBounds(root_bounds); root_window()->AddChild(keyboard_container); SetFocus(&input_client_0); @@ -557,9 +516,9 @@ float show_end_opacity = layer->opacity(); EXPECT_LT(show_start_opacity, show_end_opacity); EXPECT_EQ(gfx::Transform(), layer->transform()); - // KeyboardController should notify the bounds of keyboard window to its + // KeyboardController should notify the bounds of container window to its // observers after show animation finished. - EXPECT_EQ(keyboard_window()->bounds(), notified_bounds()); + EXPECT_EQ(keyboard_container()->bounds(), notified_bounds()); // Directly hide keyboard without delay. controller()->HideKeyboard(KeyboardController::HIDE_REASON_AUTOMATIC);
diff --git a/ui/keyboard/keyboard_layout_manager.cc b/ui/keyboard/keyboard_layout_manager.cc index c54f78c..6eee390 100644 --- a/ui/keyboard/keyboard_layout_manager.cc +++ b/ui/keyboard/keyboard_layout_manager.cc
@@ -14,52 +14,74 @@ // Overridden from aura::LayoutManager void KeyboardLayoutManager::OnWindowResized() { if (keyboard_) { - gfx::Rect window_bounds = controller_->GetContainerWindow()->bounds(); - // Keep the same height when window resize. It usually get called when - // screen rotate. - int height = keyboard_->bounds().height(); - keyboard_->SetBounds(gfx::Rect( - window_bounds.x(), - window_bounds.bottom() - height, - window_bounds.width(), - height)); + // Container window is the top level window of the virtual keyboard window. + // To support window.moveTo for the virtual keyboard window, as it actually + // moves the top level window, the container window should be set to the + // desired bounds before changing the bounds of the virtual keyboard window. + gfx::Rect container_bounds = controller_->GetContainerWindow()->bounds(); + // Always align container window and keyboard window. + SetChildBoundsDirect(keyboard_, gfx::Rect(container_bounds.size())); } } void KeyboardLayoutManager::OnWindowAddedToLayout(aura::Window* child) { DCHECK(!keyboard_); keyboard_ = child; - keyboard_->SetBounds(DefaultKeyboardBoundsFromWindowBounds( - controller_->GetContainerWindow()->bounds())); + if (controller_->keyboard_mode() == FULL_WIDTH) { + controller_->GetContainerWindow()->SetBounds(gfx::Rect()); + } else if (controller_->keyboard_mode() == FLOATING) { + controller_->GetContainerWindow()->SetBounds(child->bounds()); + SetChildBoundsDirect(keyboard_, gfx::Rect(child->bounds().size())); + } } void KeyboardLayoutManager::SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) { - // SetChildBounds can be invoked by resizing from the container or by - // resizing from the contents (through window.resizeTo call in JS). - // The flag resizing_from_contents() is used to determine the source of the - // resize. DCHECK(child == keyboard_); + // Request to change the bounds of child window (AKA the virtual keyboard + // window) should change the container window first. Then the child window is + // resized and covers the container window. Note the child's bound is only set + // in OnWindowResized. + gfx::Rect old_bounds = controller_->GetContainerWindow()->bounds(); + gfx::Rect new_bounds = requested_bounds; + if (controller_->keyboard_mode() == FULL_WIDTH) { + const gfx::Rect& window_bounds = + controller_->GetContainerWindow()->GetRootWindow()->bounds(); + new_bounds.set_y(window_bounds.height() - new_bounds.height()); + new_bounds.set_width(window_bounds.width()); + } + // Keyboard bounds should only be reset when it actually changes. Otherwise + // it interrupts the initial animation of showing the keyboard. Described in + // crbug.com/356753. + if (new_bounds == old_bounds) { + return; + } + ui::LayerAnimator* animator = controller_->GetContainerWindow()->layer()->GetAnimator(); // Stops previous animation if a window resize is requested during animation. if (animator->is_animating()) animator->StopAnimating(); - gfx::Rect old_bounds = child->bounds(); - SetChildBoundsDirect(child, requested_bounds); - if (old_bounds.height() == 0 && child->bounds().height() != 0 && - controller_->show_on_resize()) { - // The window height is set to 0 initially or before switch to an IME in a - // different extension. Virtual keyboard window may wait for this bounds - // change to correctly animate in. - controller_->ShowKeyboard(false); - } else { - // We need to send out this notification only if keyboard is visible since - // keyboard window is resized even if keyboard is hidden. - if (controller_->keyboard_visible()) - controller_->NotifyKeyboardBoundsChanging(requested_bounds); + controller_->GetContainerWindow()->SetBounds(new_bounds); + SetChildBoundsDirect(keyboard_, gfx::Rect(new_bounds.size())); + + if (controller_->keyboard_mode() == FULL_WIDTH) { + if (old_bounds.height() == 0 && child->bounds().height() != 0 && + controller_->show_on_resize()) { + // The window height is set to 0 initially or before switch to an IME in a + // different extension. Virtual keyboard window may wait for this bounds + // change to correctly animate in. + controller_->ShowKeyboard(false); + } else { + // We need to send out this notification only if keyboard is visible since + // keyboard window is resized even if keyboard is hidden. + if (controller_->keyboard_visible()) + controller_->NotifyKeyboardBoundsChanging(requested_bounds); + } + } else if (controller_->keyboard_mode() == FLOATING) { + controller_->NotifyKeyboardBoundsChanging(gfx::Rect()); } }
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc index a1cffb2..c234127 100644 --- a/ui/keyboard/keyboard_util.cc +++ b/ui/keyboard/keyboard_util.cc
@@ -57,21 +57,12 @@ namespace keyboard { -gfx::Rect DefaultKeyboardBoundsFromWindowBounds( - const gfx::Rect& window_bounds) { - // Initialize default keyboard height to 0. The keyboard window height should - // only be set by window.resizeTo in virtual keyboard web contents. Otherwise, - // the default height may conflict with the new height and causing some - // strange animation issues. - return KeyboardBoundsFromWindowBounds(window_bounds, 0); -} - -gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds, - int keyboard_height) { +gfx::Rect FullWidthKeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds, + int keyboard_height) { return gfx::Rect( - window_bounds.x(), - window_bounds.bottom() - keyboard_height, - window_bounds.width(), + root_bounds.x(), + root_bounds.bottom() - keyboard_height, + root_bounds.width(), keyboard_height); }
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h index dc1c97b..3ef2c14 100644 --- a/ui/keyboard/keyboard_util.h +++ b/ui/keyboard/keyboard_util.h
@@ -52,14 +52,11 @@ KEYBOARD_SHOW_OVERRIDE_NONE, }; -// Gets the default keyboard bounds from |window_bounds|. -KEYBOARD_EXPORT gfx::Rect DefaultKeyboardBoundsFromWindowBounds( - const gfx::Rect& window_bounds); - -// Gets the caculated keyboard bounds from |window_bounds|. The keyboard height -// is specified by |keyboard_height|. -KEYBOARD_EXPORT gfx::Rect KeyboardBoundsFromWindowBounds( - const gfx::Rect& window_bounds, int keyboard_height); +// Gets the caculated keyboard bounds from |root_bounds|. The keyboard height +// is specified by |keyboard_height|. This should be only called when keyboard +// is in FULL_WDITH mode. +KEYBOARD_EXPORT gfx::Rect FullWidthKeyboardBoundsFromRootBounds( + const gfx::Rect& root_bounds, int keyboard_height); // Sets the state of the a11y onscreen keyboard. KEYBOARD_EXPORT void SetAccessibilityKeyboardEnabled(bool enabled);
diff --git a/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc b/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc index 145b3e6..9fdc293 100644 --- a/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc +++ b/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc
@@ -95,6 +95,7 @@ case gfx::GpuMemoryBuffer::DXT1: case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: + case gfx::GpuMemoryBuffer::R_8: case gfx::GpuMemoryBuffer::BGRA_8888: case gfx::GpuMemoryBuffer::YUV_420: NOTREACHED();
diff --git a/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h b/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h index 006a4a54..c24dbb9 100644 --- a/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h +++ b/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h
@@ -31,6 +31,7 @@ virtual ~GpuMemoryBufferFactoryOzoneNativeBuffer(); // Creates a GPU memory buffer identified by |id|. + // It can be called on any thread. bool CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id, const gfx::Size& size, gfx::GpuMemoryBuffer::Format format, @@ -39,6 +40,7 @@ gfx::PluginWindowHandle surface_handle); // Destroys GPU memory buffer identified by |id|. + // It can be called on any thread. void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id); // Creates a GLImage instance for GPU memory buffer identified by |id|.
diff --git a/ui/ozone/platform/test/ozone_platform_test.cc b/ui/ozone/platform/test/ozone_platform_test.cc index fce3a9d..d94fde9 100644 --- a/ui/ozone/platform/test/ozone_platform_test.cc +++ b/ui/ozone/platform/test/ozone_platform_test.cc
@@ -25,6 +25,17 @@ namespace { +// A test implementation of PlatformEventSource that we can instantiate to make +// sure that the PlatformEventSource has an instance while in unit tests. +class TestPlatformEventSource : public ui::PlatformEventSource { + public: + TestPlatformEventSource() {} + ~TestPlatformEventSource() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource); +}; + // OzonePlatform for testing // // This platform dumps images to a file for testing purposes. @@ -67,7 +78,7 @@ window_manager_->Initialize(); // This unbreaks tests that create their own. if (!PlatformEventSource::GetInstance()) - platform_event_source_ = PlatformEventSource::CreateDefault(); + platform_event_source_.reset(new TestPlatformEventSource); KeyboardLayoutEngineManager::SetKeyboardLayoutEngine( make_scoped_ptr(new StubKeyboardLayoutEngine()));
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 3403531..aa40f44c 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -69,6 +69,7 @@ if (is_win) { sources += gypi_values.views_win_sources libs = [ + "dwmapi.lib", "imm32.lib", "oleacc.lib", ]
diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc index 52e2909..b147aa6 100644 --- a/ui/views/controls/menu/submenu_view.cc +++ b/ui/views/controls/menu/submenu_view.cc
@@ -8,7 +8,6 @@ #include "base/compiler_specific.h" #include "ui/accessibility/ax_view_state.h" -#include "ui/compositor/paint_context.h" #include "ui/compositor/paint_recorder.h" #include "ui/events/event.h" #include "ui/gfx/canvas.h"
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 8fce325..6eea993 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -647,11 +647,14 @@ } // A timer is used to continuously scroll while selecting beyond side edges. - if ((event.location().x() > 0 && event.location().x() < size().width()) || - GetDragSelectionDelay() == 0) { + const int x = event.location().x(); + if ((x >= 0 && x <= width()) || GetDragSelectionDelay() == 0) { drag_selection_timer_.Stop(); SelectThroughLastDragLocation(); } else if (!drag_selection_timer_.IsRunning()) { + // Select through the edge of the visible text, then start the scroll timer. + last_drag_location_.set_x(std::min(std::max(0, x), width())); + SelectThroughLastDragLocation(); drag_selection_timer_.Start( FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()), this, &Textfield::SelectThroughLastDragLocation);
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 8893d8c..64e131e 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -15,7 +15,6 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" -#include "ui/compositor/paint_context.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/gfx/image/image_skia.h" @@ -390,6 +389,8 @@ } void Widget::AddObserver(WidgetObserver* observer) { + // Make sure that there is no nullptr in observer list. crbug.com/471649. + CHECK(observer); observers_.AddObserver(observer); }
diff --git a/win8/delegate_execute/command_execute_impl.cc b/win8/delegate_execute/command_execute_impl.cc index 4b6636b..ba7f7f8 100644 --- a/win8/delegate_execute/command_execute_impl.cc +++ b/win8/delegate_execute/command_execute_impl.cc
@@ -19,6 +19,7 @@ #include "base/win/scoped_handle.h" #include "base/win/scoped_process_information.h" #include "base/win/win_util.h" +#include "base/win/windows_version.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -482,6 +483,16 @@ return launch_mode; } + // As of now ActivateApplication fails on Windows 10 (Build 9926). + // Until there is some clarity on special status of browser in metro mode on + // Windows 10, we just disable Chrome metro mode so that browser remains + // usable. + if (base::win::GetVersion() >= base::win::VERSION_WIN10) { + launch_mode = ECHUIM_DESKTOP; + launch_mode_determined = true; + return launch_mode; + } + // Use the previous mode if available. Else launch in desktop mode. DWORD reg_value; if (reg_key.ReadValueDW(chrome::kLaunchModeValue,