Merge from Chromium at DEPS revision 40.0.2214.38

This commit was generated by merge_to_master.py.

Change-Id: I5e881388509cd5fb3882f4ba2ef6663965219173
diff --git a/DEPS b/DEPS
index a896bfb..96d5aef 100644
--- a/DEPS
+++ b/DEPS
@@ -68,7 +68,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '4dc95e74e1acc75f4eab08bc771874cd2a9c3a9b',
+  'pdfium_revision': '0e46ce2948c8b45e9e5adcf6c4cb27620d5ba8ae',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
diff --git a/android_webview/android_webview_jarjar_content_resources.target.darwin-arm.mk b/android_webview/android_webview_jarjar_content_resources.target.darwin-arm.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.darwin-arm.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.darwin-arm.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.darwin-arm64.mk b/android_webview/android_webview_jarjar_content_resources.target.darwin-arm64.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.darwin-arm64.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.darwin-arm64.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.darwin-mips.mk b/android_webview/android_webview_jarjar_content_resources.target.darwin-mips.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.darwin-mips.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.darwin-mips.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.darwin-mips64.mk b/android_webview/android_webview_jarjar_content_resources.target.darwin-mips64.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.darwin-mips64.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.darwin-mips64.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.darwin-x86.mk b/android_webview/android_webview_jarjar_content_resources.target.darwin-x86.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.darwin-x86.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.darwin-x86.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.darwin-x86_64.mk b/android_webview/android_webview_jarjar_content_resources.target.darwin-x86_64.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.darwin-x86_64.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.darwin-x86_64.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.linux-arm.mk b/android_webview/android_webview_jarjar_content_resources.target.linux-arm.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.linux-arm.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.linux-arm.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.linux-arm64.mk b/android_webview/android_webview_jarjar_content_resources.target.linux-arm64.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.linux-arm64.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.linux-arm64.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.linux-mips.mk b/android_webview/android_webview_jarjar_content_resources.target.linux-mips.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.linux-mips.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.linux-mips.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.linux-mips64.mk b/android_webview/android_webview_jarjar_content_resources.target.linux-mips64.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.linux-mips64.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.linux-mips64.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.linux-x86.mk b/android_webview/android_webview_jarjar_content_resources.target.linux-x86.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.linux-x86.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.linux-x86.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/android_webview_jarjar_content_resources.target.linux-x86_64.mk b/android_webview/android_webview_jarjar_content_resources.target.linux-x86_64.mk
index 7118a65..0607057 100644
--- a/android_webview/android_webview_jarjar_content_resources.target.linux-x86_64.mk
+++ b/android_webview/android_webview_jarjar_content_resources.target.linux-x86_64.mk
@@ -19,7 +19,7 @@
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp: $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/jarjar_resources.py $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-hdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-mdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/bubble_arrow_up.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/ondemand_overlay.9.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_search_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/ic_menu_share_holo_light.png $(LOCAL_PATH)/content/public/android/java/res/drawable-xxxhdpi/pageinfo_warning_major.png $(LOCAL_PATH)/content/public/android/java/res/layout/validation_message_bubble.xml $(LOCAL_PATH)/content/public/android/java/res/menu/select_action_menu.xml $(LOCAL_PATH)/content/public/android/java/res/values-v17/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values-v21/styles.xml $(LOCAL_PATH)/content/public/android/java/res/values/attrs.xml $(LOCAL_PATH)/content/public/android/java/res/values/dimens.xml $(LOCAL_PATH)/content/public/android/java/res/values/strings.xml $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Copying and jar-jaring resources for android_webview_jarjar_content_resources ($@)"
 	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources; python ../build/android/gyp/jarjar_resources.py --input-dir ../content/public/android/java/res --output-dir "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_res" --rules-path ../android_webview/build/jarjar-rules.txt --stamp "$(gyp_shared_intermediate_dir)/android_webview_jarjar_content_resources/jarjar_resources.stamp"
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index b29821b..0c8546a 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -364,6 +364,7 @@
 void AwContentBrowserClient::SelectClientCertificate(
       int render_process_id,
       int render_frame_id,
+      const net::HttpNetworkSession* network_session,
       net::SSLCertRequestInfo* cert_request_info,
       const base::Callback<void(net::X509Certificate*)>& callback) {
   AwContentsClientBridgeBase* client =
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 9bd6f03..7ae700d 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -106,6 +106,7 @@
   virtual void SelectClientCertificate(
       int render_process_id,
       int render_frame_id,
+      const net::HttpNetworkSession* network_session,
       net::SSLCertRequestInfo* cert_request_info,
       const base::Callback<void(net::X509Certificate*)>& callback) override;
   virtual blink::WebNotificationPermission
diff --git a/android_webview/common/aw_crash_handler.cc b/android_webview/common/aw_crash_handler.cc
index a637298..fbd4285 100644
--- a/android_webview/common/aw_crash_handler.cc
+++ b/android_webview/common/aw_crash_handler.cc
@@ -6,6 +6,9 @@
 
 #include <android/log.h>
 #include <signal.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
 
 #include "base/logging.h"
 
@@ -27,6 +30,14 @@
   if (g_crash_msg_ptr != NULL)
     __android_log_write(ANDROID_LOG_ERROR, "chromium", g_crash_msg_ptr);
 
+  // Detect if some buggy code in the embedder did reinstall the handler using
+  // signal() instead of sigaction() (which would cause |info| to be invalid).
+  struct sigaction cur_handler;
+  if (sigaction(sig, NULL, &cur_handler) != 0 ||
+      (cur_handler.sa_flags & SA_SIGINFO) == 0) {
+    info = NULL;
+  }
+
   // We served our purpose. Now restore the old crash handlers. If the embedder
   // did register a custom crash handler, it will be invoked by the kernel after
   // this function returns. Otherwise, this will end up invoking the default
@@ -36,6 +47,17 @@
       signal(kExceptionSignals[i], SIG_DFL);
     }
   }
+
+  if ((info != NULL && info->si_pid) || sig == SIGABRT) {
+    // This signal was triggered by somebody sending us the signal with kill().
+    // In order to retrigger it, we have to queue a new signal by calling
+    // kill() ourselves.  The special case (si_pid == 0 && sig == SIGABRT) is
+    // due to the kernel sending a SIGABRT from a user request via SysRQ.
+    if (syscall(__NR_tgkill, getpid(), syscall(__NR_gettid), sig) < 0) {
+      // If we failed to kill ourselves resort to terminating uncleanly.
+      exit(1);
+    }
+  }
 }
 
 }  // namespace
@@ -65,6 +87,7 @@
   memset(&sa, 0, sizeof(sa));
   sigemptyset(&sa.sa_mask);
 
+  // Mask all exception signals when we're handling one of them.
   for (uint32_t i = 0; i < arraysize(kExceptionSignals); ++i)
     sigaddset(&sa.sa_mask, kExceptionSignals[i]);
 
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 7f0dc03..d1fd6ce 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -811,8 +811,9 @@
 
         long nativeWebContents = nativeGetWebContents(mNativeAwContents);
 
-        mWindowAndroid = mContext instanceof Activity
-                ? new ActivityWindowAndroid((Activity) mContext)
+        Activity activity = ContentViewCore.activityFromContext(mContext);
+        mWindowAndroid = activity != null
+                ? new ActivityWindowAndroid(activity)
                 : new WindowAndroid(mContext.getApplicationContext());
         mContentViewCore = createAndInitializeContentViewCore(
                 mContainerView, mContext, mInternalAccessAdapter, nativeWebContents,
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java
index 253a361..e39252f 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwJavaBridgeTest.java
@@ -43,9 +43,9 @@
                             }
                     });
                     // Destroying one AwContents from within the JS callback should still
-                    // leave others functioning.
-                    loadDataSync(view2.getAwContents(), client2.getOnPageFinishedHelper(),
-                            html, "text/html", false);
+                    // leave others functioning. Note that we must do this asynchronously,
+                    // as Blink thread is currently blocked waiting for this method to finish.
+                    loadDataAsync(view2.getAwContents(), html, "text/html", false);
                 } catch (Throwable t) {
                     throw new RuntimeException(t);
                 }
@@ -66,9 +66,99 @@
         // Ensure the JS interface object is there, and invoke the test method.
         assertEquals("\"function\"", executeJavaScriptAndWaitForResult(
                 awContents, mContentsClient, "typeof test.destroy"));
+        int currentCallCount = client2.getOnPageFinishedHelper().getCallCount();
         awContents.evaluateJavaScript("test.destroy()", null);
 
-        client2.getOnPageFinishedHelper().waitForCallback(
-                client2.getOnPageFinishedHelper().getCallCount());
+        client2.getOnPageFinishedHelper().waitForCallback(currentCallCount);
+    }
+
+    @SmallTest
+    @Feature({"AndroidWebView", "Android-JavaBridge"})
+    public void testTwoWebViewsCreatedSimultaneously() throws Throwable {
+        final AwContents awContents1 = mTestContainerView.getAwContents();
+        final TestAwContentsClient client2 = new TestAwContentsClient();
+        final AwTestContainerView view2 = createAwTestContainerViewOnMainSync(client2);
+        final AwContents awContents2 = view2.getAwContents();
+
+        enableJavaScriptOnUiThread(awContents1);
+        enableJavaScriptOnUiThread(awContents2);
+
+        class Test {
+            Test(int value) {
+                mValue = value;
+            }
+            @JavascriptInterface
+            public int getValue() {
+                return mValue;
+            }
+            private int mValue;
+        }
+
+        runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    awContents1.addPossiblyUnsafeJavascriptInterface(new Test(1), "test", null);
+                    awContents2.addPossiblyUnsafeJavascriptInterface(new Test(2), "test", null);
+                }
+        });
+        final String html = "<html>Hello World</html>";
+        loadDataSync(awContents1, mContentsClient.getOnPageFinishedHelper(), html,
+                "text/html", false);
+        loadDataSync(awContents2, client2.getOnPageFinishedHelper(), html,
+                "text/html", false);
+
+        assertEquals("1",
+                executeJavaScriptAndWaitForResult(awContents1, mContentsClient, "test.getValue()"));
+        assertEquals("2",
+                executeJavaScriptAndWaitForResult(awContents2, client2, "test.getValue()"));
+    }
+
+    @SmallTest
+    @Feature({"AndroidWebView", "Android-JavaBridge"})
+    public void testTwoWebViewsSecondCreatedAfterLoadingInFirst() throws Throwable {
+        final AwContents awContents1 = mTestContainerView.getAwContents();
+        enableJavaScriptOnUiThread(awContents1);
+
+        class Test {
+            Test(int value) {
+                mValue = value;
+            }
+            @JavascriptInterface
+            public int getValue() {
+                return mValue;
+            }
+            private int mValue;
+        }
+
+        runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    awContents1.addPossiblyUnsafeJavascriptInterface(new Test(1), "test", null);
+                }
+        });
+        final String html = "<html>Hello World</html>";
+        loadDataSync(awContents1, mContentsClient.getOnPageFinishedHelper(), html,
+                "text/html", false);
+        assertEquals("1",
+                executeJavaScriptAndWaitForResult(awContents1, mContentsClient, "test.getValue()"));
+
+        final TestAwContentsClient client2 = new TestAwContentsClient();
+        final AwTestContainerView view2 = createAwTestContainerViewOnMainSync(client2);
+        final AwContents awContents2 = view2.getAwContents();
+        enableJavaScriptOnUiThread(awContents2);
+
+        runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    awContents2.addPossiblyUnsafeJavascriptInterface(new Test(2), "test", null);
+                }
+        });
+        loadDataSync(awContents2, client2.getOnPageFinishedHelper(), html,
+                "text/html", false);
+
+        assertEquals("1",
+                executeJavaScriptAndWaitForResult(awContents1, mContentsClient, "test.getValue()"));
+        assertEquals("2",
+                executeJavaScriptAndWaitForResult(awContents2, client2, "test.getValue()"));
     }
 }
diff --git a/build/android/setup.gyp b/build/android/setup.gyp
index f10ab3e..7dce19d 100644
--- a/build/android/setup.gyp
+++ b/build/android/setup.gyp
@@ -12,26 +12,13 @@
           # <(SHARED_LIB_DIR)
           'target_name': 'copy_system_libraries',
           'type': 'none',
-          'conditions': [
-            ['target_arch=="arm" and arm_thumb==1', {
-              'copies': [
-                {
-                  'destination': '<(SHARED_LIB_DIR)/',
-                  'files': [
-                    '<(android_stlport_libs_dir)/thumb/libstlport_shared.so',
-                  ],
-                },
+          'copies': [
+            {
+              'destination': '<(SHARED_LIB_DIR)/',
+              'files': [
+                '<(android_stlport_libs_dir)/libstlport_shared.so',
               ],
-            }, {
-              'copies': [
-                {
-                  'destination': '<(SHARED_LIB_DIR)/',
-                  'files': [
-                    '<(android_stlport_libs_dir)/libstlport_shared.so',
-                  ],
-                },
-              ],
-            }],
+            },
           ],
         },
       ],
diff --git a/build/common.gypi b/build/common.gypi
index 256515a..7ec5ae2 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -2295,6 +2295,11 @@
         'arm_thumb%': 1,
       }],
 
+      # Set default compiler flags depending on MIPS architecture variant.
+      ['target_arch=="mipsel" and mips_arch_variant=="r2" and android_webview_build==0', {
+        'mips_fpu_mode%': 'fp32',
+      }],
+
       ['android_webview_build==1', {
         # The WebView build gets its cpu-specific flags from the Android build system.
         'arm_arch%': '',
@@ -2302,6 +2307,7 @@
         'arm_fpu%': '',
         'arm_float_abi%': '',
         'arm_thumb%': 0,
+        'mips_fpu_mode%': '',
       }],
 
       # Enable brlapi by default for chromeos.
@@ -2359,7 +2365,6 @@
       }, {
          'use_seccomp_bpf%': 0,
       }],
-
       # Set component build with LTO until all tests pass.
       # This also reduces link time.
       ['use_lto==1', {
@@ -2398,7 +2403,7 @@
     # Whether to allow building of the GPU-related isolates.
     'archive_gpu_tests%': 0,
 
-    # Whether to allow building of chromoting related isolates.
+     # Whether to allow building of chromoting related isolates.
     'archive_chromoting_tests%': 0,
   },
   'target_defaults': {
@@ -4660,19 +4665,10 @@
                   '--sysroot=<(android_ndk_sysroot)',
                   '-nostdlib',
                 ],
-                'variables': {
-                  'conditions': [
-                    ['target_arch=="arm" and arm_thumb==1', {
-                      'thumb_option%': '-mthumb',
-                    }, {
-                      'thumb_option%': '',
-                    }],
-                  ],
-                },
                 'libraries': [
                   '-l<(android_stlport_library)',
                   # Manually link the libgcc.a that the cross compiler uses.
-                  '<!(<(android_toolchain)/*-gcc <(thumb_option) -print-libgcc-file-name)',
+                  '<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
                   '-lc',
                   '-ldl',
                   '-lm',
@@ -4737,12 +4733,8 @@
                 'cflags': [
                   '-isystem<(android_stlport_include)',
                 ],
-                'conditions': [
-                  ['target_arch=="arm" and arm_thumb==1', {
-                    'ldflags': [ '-L<(android_stlport_libs_dir)/thumb' ]
-                  }, {
-                    'ldflags': [ '-L<(android_stlport_libs_dir)' ]
-                  }],
+                'ldflags': [
+                  '-L<(android_stlport_libs_dir)',
                 ],
               }, { # else: android_webview_build!=0
                 'aosp_build_settings': {
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index ce9a175..409bba9 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -37,23 +37,6 @@
     android_chrome_build_id = "\"\""
   }
 
-  # ABI ------------------------------------------------------------------------
-
-  if (cpu_arch == "x86") {
-    android_app_abi = "x86"
-  } else if (cpu_arch == "arm") {
-    import("//build/config/arm.gni")
-    if (arm_version < 7) {
-      android_app_abi = "armeabi"
-    } else {
-      android_app_abi = "armeabi-v7a"
-    }
-  } else if (cpu_arch == "mipsel") {
-    android_app_abi = "mips"
-  } else {
-    assert(false, "Unknown Android ABI: " + cpu_arch)
-  }
-
   # Host stuff -----------------------------------------------------------------
 
   # Defines the name the Android build gives to the current host CPU
@@ -123,13 +106,8 @@
     android_prebuilt_arch = "android-arm"
     _binary_prefix = "arm-linux-androideabi"
     android_toolchain_root = "$arm_android_toolchain_root"
-    if (arm_use_thumb) {
-      android_libgcc_file =
-        "$android_toolchain_root/lib/gcc/arm-linux-androideabi/${_android_toolchain_version}/thumb/libgcc.a"
-    } else {
-      android_libgcc_file =
+    android_libgcc_file =
         "$android_toolchain_root/lib/gcc/arm-linux-androideabi/${_android_toolchain_version}/libgcc.a"
-    }
   } else if (cpu_arch == "mipsel") {
     android_prebuilt_arch = "android-mips"
     _binary_prefix = "mipsel-linux-android"
@@ -152,6 +130,23 @@
   } else {
     android_stlport_library = "stlport_static"
   }
+
+  # ABI ------------------------------------------------------------------------
+
+  if (cpu_arch == "x86") {
+    android_app_abi = "x86"
+  } else if (cpu_arch == "arm") {
+    import("//build/config/arm.gni")
+    if (arm_version < 7) {
+      android_app_abi = "armeabi"
+    } else {
+      android_app_abi = "armeabi-v7a"
+    }
+  } else if (cpu_arch == "mipsel") {
+    android_app_abi = "mips"
+  } else {
+    assert(false, "Unknown Android ABI: " + cpu_arch)
+  }
 } else {
   if (!defined(is_android_webview_build)) {
     is_android_webview_build = false
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 3d1b341..ac73fb6 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -481,15 +481,9 @@
     # caution.
     android_stlport_root = "$android_ndk_root/sources/cxx-stl/stlport"
 
-    cflags += [
-      "-isystem" + rebase_path("$android_stlport_root/stlport",
-                               root_build_dir)
-    ]
-    if (arm_use_thumb) {
-      lib_dirs += [ "$android_stlport_root/libs/$android_app_abi/thumb" ]
-    } else {
-      lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
-    }
+    cflags += [ "-isystem" +
+                rebase_path("$android_stlport_root/stlport", root_build_dir) ]
+    lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
 
     if (component_mode == "shared_library") {
       libs += [ "stlport_shared" ]
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index be6e68b..a18bf98 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=472e9e85cdec
+LASTCHANGE=07329508ba1d
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index 730df68..0266d2a 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=186261
+LASTCHANGE=186783
diff --git a/cc/base/rolling_time_delta_history.cc b/cc/base/rolling_time_delta_history.cc
index 0f95cc5..db04f58 100644
--- a/cc/base/rolling_time_delta_history.cc
+++ b/cc/base/rolling_time_delta_history.cc
@@ -26,10 +26,6 @@
   chronological_sample_deque_.push_back(it);
 }
 
-size_t RollingTimeDeltaHistory::SampleCount() {
-  return sample_set_.size();
-}
-
 void RollingTimeDeltaHistory::Clear() {
   chronological_sample_deque_.clear();
   sample_set_.clear();
diff --git a/cc/base/rolling_time_delta_history.h b/cc/base/rolling_time_delta_history.h
index 603c813..e51fb86 100644
--- a/cc/base/rolling_time_delta_history.h
+++ b/cc/base/rolling_time_delta_history.h
@@ -23,8 +23,6 @@
 
   void InsertSample(base::TimeDelta time);
 
-  size_t SampleCount();
-
   void Clear();
 
   // Returns the smallest sample that is greater than or equal to the specified
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 822fcf3..d43dd02 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -1101,8 +1101,12 @@
     if (maximum_scale) {
       gfx::Size bounds_at_maximum_scale = gfx::ToCeiledSize(
           gfx::ScaleSize(pile_->tiling_size(), maximum_scale));
-      if (bounds_at_maximum_scale.GetArea() <=
-          layer_tree_impl()->device_viewport_size().GetArea())
+      int64 maximum_area = static_cast<int64>(bounds_at_maximum_scale.width()) *
+                           static_cast<int64>(bounds_at_maximum_scale.height());
+      gfx::Size viewport = layer_tree_impl()->device_viewport_size();
+      int64 viewport_area = static_cast<int64>(viewport.width()) *
+                            static_cast<int64>(viewport.height());
+      if (maximum_area <= viewport_area)
         can_raster_at_maximum_scale = true;
     }
     // Use the computed scales for the raster scale directly, do not try to use
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 4b42eca..b75aa63 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -1872,6 +1872,9 @@
 TEST_F(PictureLayerImplTest, HighResRequiredWhenUnsharedActiveAllReady) {
   gfx::Size layer_bounds(400, 400);
   gfx::Size tile_size(100, 100);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   // No tiles shared.
@@ -1893,6 +1896,9 @@
 TEST_F(PictureLayerImplTest, HighResRequiredWhenMissingHighResFlagOn) {
   gfx::Size layer_bounds(400, 400);
   gfx::Size tile_size(100, 100);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   // All tiles shared (no invalidation).
@@ -1917,6 +1923,9 @@
 TEST_F(PictureLayerImplTest, AllHighResRequiredEvenIfShared) {
   gfx::Size layer_bounds(400, 400);
   gfx::Size tile_size(100, 100);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   CreateHighLowResAndSetAllTilesVisible();
@@ -1991,6 +2000,9 @@
 TEST_F(PictureLayerImplTest, HighResRequiredIfActiveCantHaveTiles) {
   gfx::Size layer_bounds(400, 400);
   gfx::Size tile_size(100, 100);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
   scoped_refptr<FakePicturePileImpl> pending_pile =
       FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
   scoped_refptr<FakePicturePileImpl> active_pile =
@@ -3136,6 +3148,8 @@
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   // Make sure some tiles are not shared.
@@ -3163,6 +3177,8 @@
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   // Make sure some tiles are not shared.
@@ -3186,6 +3202,8 @@
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   // Make sure some tiles are not shared.
@@ -3210,6 +3228,8 @@
   gfx::Size tile_size(100, 100);
   gfx::Size layer_bounds(1000, 1000);
 
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   // Make sure some tiles are not shared.
@@ -3297,6 +3317,9 @@
 TEST_F(NoLowResPictureLayerImplTest, AllHighResRequiredEvenIfShared) {
   gfx::Size layer_bounds(400, 400);
   gfx::Size tile_size(100, 100);
+
+  host_impl_.SetViewportSize(layer_bounds);
+
   SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size);
 
   CreateHighLowResAndSetAllTilesVisible();
@@ -3658,6 +3681,8 @@
   gfx::Size tile_size(400, 400);
   gfx::Size layer_bounds(1000, 2000);
 
+  host_impl_.SetViewportSize(layer_bounds);
+
   scoped_refptr<FakePicturePileImpl> pending_pile =
       FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
   scoped_refptr<FakePicturePileImpl> active_pile =
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc
index 9c814be..e0676d2 100644
--- a/cc/layers/tiled_layer_unittest.cc
+++ b/cc/layers/tiled_layer_unittest.cc
@@ -260,6 +260,8 @@
 };
 
 TEST_F(TiledLayerTest, PushDirtyTiles) {
+  layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
+
   scoped_refptr<FakeTiledLayer> layer =
       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   scoped_ptr<FakeTiledLayerImpl> layer_impl =
@@ -289,6 +291,8 @@
 }
 
 TEST_F(TiledLayerTest, Scale) {
+  layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
+
   layer_tree_host_->SetDeviceScaleFactor(1.5);
 
   scoped_refptr<FakeTiledLayer> layer =
@@ -351,6 +355,8 @@
 }
 
 TEST_F(TiledLayerTest, PushDeletedTiles) {
+  layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
+
   scoped_refptr<FakeTiledLayer> layer =
       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   scoped_ptr<FakeTiledLayerImpl> layer_impl =
@@ -1200,6 +1206,8 @@
 }
 
 TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) {
+  layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
+
   scoped_refptr<FakeTiledLayer> layer =
       make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
   RenderSurfaceLayerList render_surface_layer_list;
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index a472475..214b989 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -99,6 +99,8 @@
   switch (mode) {
     case SkXfermode::kSrcOver_Mode:
       return BlendModeNormal;
+    case SkXfermode::kScreen_Mode:
+      return BlendModeScreen;
     case SkXfermode::kOverlay_Mode:
       return BlendModeOverlay;
     case SkXfermode::kDarken_Mode:
@@ -129,7 +131,7 @@
       return BlendModeLuminosity;
     default:
       NOTREACHED();
-      return BlendModeNormal;
+      return BlendModeNone;
   }
 }
 
@@ -866,99 +868,8 @@
   return background_with_filters;
 }
 
-scoped_ptr<ScopedResource>
-GLRenderer::ApplyInverseTransformForBackgroundFilters(
-    DrawingFrame* frame,
-    const RenderPassDrawQuad* quad,
-    const gfx::Transform& contents_device_transform,
-    skia::RefPtr<SkImage> filtered_device_background,
-    const gfx::Rect& backdrop_bounding_rect) {
-  // This method draws a background filter, which applies a filter to any pixels
-  // behind the quad and seen through its background.  The algorithm works as
-  // follows:
-  // 1. Read the pixels in the bounding box into a buffer.
-  // Moved to GLRenderer::GetBackdropBoundingBoxForRenderPassQuad().
-  // 2. Read the pixels in the bounding box into a buffer R.
-  // Moved to GLRenderer::GetBackdropTexture().
-  // 3. Apply the background filter to R, so that it is applied in the pixels'
-  // coordinate space. Moved to GLRenderer::ApplyBackgroundFilters().
-  // 4. Apply the quad's inverse transform to map the pixels in R into the
-  // quad's content space. This implicitly clips R by the content bounds of the
-  // quad since the destination texture has bounds matching the quad's content.
-  // 5. Draw the background texture for the contents using the same transform as
-  // used to draw the contents itself. This is done without blending to replace
-  // the current background pixels with the new filtered background.
-  // 6. Draw the contents of the quad over drop of the new background with
-  // blending, as per usual. The filtered background pixels will show through
-  // any non-opaque pixels in this draws.
-  //
-  // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
-
-  // TODO(danakj): When this algorithm changes, update
-  // LayerTreeHost::PrioritizeTextures() accordingly.
-
-  DCHECK(filtered_device_background);
-
-  GrTexture* texture = filtered_device_background->getTexture();
-
-  scoped_ptr<ScopedResource> background_texture =
-      ScopedResource::Create(resource_provider_);
-  background_texture->Allocate(
-      quad->rect.size(),
-      ResourceProvider::TextureHintImmutableFramebuffer,
-      RGBA_8888);
-
-  const RenderPass* target_render_pass = frame->current_render_pass;
-  bool using_background_texture =
-      UseScopedTexture(frame, background_texture.get(), quad->rect);
-
-  if (using_background_texture) {
-    // Copy the readback pixels from device to the background texture for the
-    // surface.
-
-    gfx::Transform contents_device_transform_inverse(
-        gfx::Transform::kSkipInitialization);
-    bool did_invert = contents_device_transform.GetInverse(
-        &contents_device_transform_inverse);
-    DCHECK(did_invert);
-    gfx::Transform device_to_framebuffer_transform;
-    QuadRectTransform(
-        &device_to_framebuffer_transform, gfx::Transform(), quad->rect);
-    device_to_framebuffer_transform.PreconcatTransform(
-        contents_device_transform_inverse);
-
-#ifndef NDEBUG
-    GLC(gl_, gl_->ClearColor(0, 0, 1, 1));
-    gl_->Clear(GL_COLOR_BUFFER_BIT);
-#endif
-
-    // The background_texture is oriented the same as the frame buffer.
-    // The transform we are copying with has a vertical flip, as well as
-    // the |device_to_framebuffer_transform|, which cancel each other out. So do
-    // not flip the contents in the shader to maintain orientation.
-    bool flip_vertically = false;
-
-    CopyTextureToFramebuffer(frame,
-                             texture->getTextureHandle(),
-                             backdrop_bounding_rect,
-                             device_to_framebuffer_transform,
-                             flip_vertically);
-  }
-
-  UseRenderPass(frame, target_render_pass);
-
-  if (!using_background_texture)
-    return nullptr;
-  return background_texture.Pass();
-}
-
 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
                                     const RenderPassDrawQuad* quad) {
-  SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode;
-  SetBlendEnabled(
-      CanApplyBlendModeUsingBlendFunc(blend_mode) &&
-      (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode)));
-
   ScopedResource* contents_texture =
       render_pass_textures_.get(quad->render_pass_id);
   if (!contents_texture || !contents_texture->id())
@@ -984,62 +895,59 @@
     SetupQuadForAntialiasing(contents_device_transform, quad,
                              &surface_quad, edge);
 
-  bool need_background_texture = !CanApplyBlendModeUsingBlendFunc(blend_mode) ||
-                                 ShouldApplyBackgroundFilters(frame, quad);
+  SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode;
+  bool use_shaders_for_blending =
+      !CanApplyBlendModeUsingBlendFunc(blend_mode) ||
+      ShouldApplyBackgroundFilters(frame, quad) ||
+      settings_->force_blending_with_shaders;
 
   scoped_ptr<ScopedResource> background_texture;
   skia::RefPtr<SkImage> background_image;
   gfx::Rect background_rect;
-  if (need_background_texture) {
+  if (use_shaders_for_blending) {
     // Compute a bounding box around the pixels that will be visible through
     // the quad.
     background_rect = GetBackdropBoundingBoxForRenderPassQuad(
         frame, quad, contents_device_transform, use_aa);
-  }
 
-  if (!background_rect.IsEmpty()) {
-    // The pixels from the filtered background should completely replace the
-    // current pixel values.
-    bool disable_blending = blend_enabled();
-    if (disable_blending)
-      SetBlendEnabled(false);
+    if (!background_rect.IsEmpty()) {
+      // The pixels from the filtered background should completely replace the
+      // current pixel values.
+      if (blend_enabled())
+        SetBlendEnabled(false);
 
-    // Read the pixels in the bounding box into a buffer R.
-    scoped_ptr<ScopedResource> scoped_background_texture =
-        GetBackdropTexture(background_rect);
+      // Read the pixels in the bounding box into a buffer R.
+      // This function allocates a texture, which should contribute to the
+      // amount of memory used by render surfaces:
+      // LayerTreeHost::CalculateMemoryForRenderSurfaces.
+      background_texture = GetBackdropTexture(background_rect);
 
-    skia::RefPtr<SkImage> background_with_filters;
-    if (ShouldApplyBackgroundFilters(frame, quad) &&
-        scoped_background_texture) {
-      // Apply the background filters to R, so that it is applied in the pixels'
-      // coordinate space.
-      background_with_filters =
-          ApplyBackgroundFilters(frame, quad, scoped_background_texture.get());
-    }
-
-    if (CanApplyBlendModeUsingBlendFunc(blend_mode) &&
-        background_with_filters) {
-      // The background with filters will be copied to the frame buffer.
-      // Apply the quad's inverse transform to map the pixels in R into the
-      // quad's content space. This implicitly clips R by the content bounds of
-      // the quad since the destination texture has bounds matching the quad's
-      // content.
-      background_texture = ApplyInverseTransformForBackgroundFilters(
-          frame, quad, contents_device_transform, background_with_filters,
-          background_rect);
-    } else if (!CanApplyBlendModeUsingBlendFunc(blend_mode)) {
-      if (background_with_filters) {
-        // The background with filters will be used as backdrop for blending.
-        background_image = background_with_filters;
-      } else {
-        background_texture = scoped_background_texture.Pass();
+      if (ShouldApplyBackgroundFilters(frame, quad) && background_texture) {
+        // Apply the background filters to R, so that it is applied in the
+        // pixels' coordinate space.
+        background_image =
+            ApplyBackgroundFilters(frame, quad, background_texture.get());
       }
     }
 
-    if (disable_blending)
-      SetBlendEnabled(true);
+    if (!background_texture) {
+      // Something went wrong with reading the backdrop.
+      DCHECK(!background_image);
+      use_shaders_for_blending = false;
+    } else if (background_image) {
+      background_texture.reset();
+    } else if (CanApplyBlendModeUsingBlendFunc(blend_mode) &&
+               ShouldApplyBackgroundFilters(frame, quad)) {
+      // Something went wrong with applying background filters to the backdrop.
+      use_shaders_for_blending = false;
+      background_texture.reset();
+    }
   }
 
+  SetBlendEnabled(
+      !use_shaders_for_blending &&
+      (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode)));
+
   // TODO(senorblanco): Cache this value so that we don't have to do it for both
   // the surface and its replica.  Apply filters to the contents texture.
   skia::RefPtr<SkImage> filter_image;
@@ -1072,25 +980,6 @@
     }
   }
 
-  if (background_texture && ShouldApplyBackgroundFilters(frame, quad)) {
-    // Draw the background texture if it has some filters applied.
-    DCHECK(CanApplyBlendModeUsingBlendFunc(blend_mode));
-    DCHECK(background_texture->size() == quad->rect.size());
-    ResourceProvider::ScopedReadLockGL lock(resource_provider_,
-                                            background_texture->id());
-
-    // The background_texture is oriented the same as the frame buffer. The
-    // transform we are copying with has a vertical flip, so flip the contents
-    // in the shader to maintain orientation
-    bool flip_vertically = true;
-
-    CopyTextureToFramebuffer(frame,
-                             lock.texture_id(),
-                             quad->rect,
-                             quad->quadTransform(),
-                             flip_vertically);
-  }
-
   scoped_ptr<ResourceProvider::ScopedSamplerGL> mask_resource_lock;
   unsigned mask_texture_id = 0;
   SamplerType mask_sampler = SamplerTypeNA;
@@ -1101,9 +990,6 @@
     mask_sampler = SamplerTypeFromTextureTarget(mask_resource_lock->target());
   }
 
-  // TODO(danakj): use the background_texture and blend the background in with
-  // this draw instead of having a separate copy of the background texture.
-
   scoped_ptr<ResourceProvider::ScopedSamplerGL> contents_resource_lock;
   if (filter_image) {
     GrTexture* texture = filter_image->getTexture();
@@ -1117,7 +1003,7 @@
               contents_resource_lock->target());
   }
 
-  if (CanApplyBlendModeUsingBlendFunc(blend_mode)) {
+  if (!use_shaders_for_blending) {
     if (!use_blend_equation_advanced_coherent_ && use_blend_equation_advanced_)
       GLC(gl_, gl_->BlendBarrierKHR());
 
@@ -1144,10 +1030,10 @@
   int shader_backdrop_location = -1;
   int shader_backdrop_rect_location = -1;
 
-  BlendMode shader_blend_mode = ((background_texture || background_image) &&
-                                 !CanApplyBlendModeUsingBlendFunc(blend_mode))
+  DCHECK_EQ(background_texture || background_image, use_shaders_for_blending);
+  BlendMode shader_blend_mode = use_shaders_for_blending
                                     ? BlendModeFromSkXfermode(blend_mode)
-                                    : BlendModeNormal;
+                                    : BlendModeNone;
 
   if (use_aa && mask_texture_id && !use_color_matrix) {
     const RenderPassMaskProgramAA* program = GetRenderPassMaskProgramAA(
@@ -1424,7 +1310,7 @@
   if (filter_image)
     GLC(gl_, gl_->Flush());
 
-  if (CanApplyBlendModeUsingBlendFunc(blend_mode))
+  if (!use_shaders_for_blending)
     RestoreBlendFuncToDefault(blend_mode);
 }
 
@@ -2452,43 +2338,6 @@
   GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
 }
 
-void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame,
-                                          int texture_id,
-                                          const gfx::Rect& rect,
-                                          const gfx::Transform& draw_matrix,
-                                          bool flip_vertically) {
-  TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
-      gl_, &highp_threshold_cache_, highp_threshold_min_, rect.bottom_right());
-
-  const RenderPassProgram* program =
-      GetRenderPassProgram(tex_coord_precision, BlendModeNormal);
-  SetUseProgram(program->program());
-
-  GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0));
-
-  if (flip_vertically) {
-    GLC(gl_,
-        gl_->Uniform4f(program->vertex_shader().tex_transform_location(),
-                       0.f,
-                       1.f,
-                       1.f,
-                       -1.f));
-  } else {
-    GLC(gl_,
-        gl_->Uniform4f(program->vertex_shader().tex_transform_location(),
-                       0.f,
-                       0.f,
-                       1.f,
-                       1.f));
-  }
-
-  SetShaderOpacity(1.f, program->fragment_shader().alpha_location());
-  DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_));
-  GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id));
-  DrawQuadGeometry(
-      frame, draw_matrix, rect, program->vertex_shader().matrix_location());
-}
-
 void GLRenderer::Finish() {
   TRACE_EVENT0("cc", "GLRenderer::Finish");
   GLC(gl_, gl_->Finish());
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 4930204..ecadebb 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -167,12 +167,6 @@
       DrawingFrame* frame,
       const RenderPassDrawQuad* quad,
       ScopedResource* background_texture);
-  scoped_ptr<ScopedResource> ApplyInverseTransformForBackgroundFilters(
-      DrawingFrame* frame,
-      const RenderPassDrawQuad* quad,
-      const gfx::Transform& contents_device_transform,
-      skia::RefPtr<SkImage> backdrop_bitmap,
-      const gfx::Rect& backdrop_bounding_rect);
 
   void DrawRenderPassQuad(DrawingFrame* frame, const RenderPassDrawQuad* quad);
   void DrawSolidColorQuad(const DrawingFrame* frame,
@@ -208,12 +202,6 @@
                         int matrix_location);
   void SetUseProgram(unsigned program);
 
-  void CopyTextureToFramebuffer(const DrawingFrame* frame,
-                                int texture_id,
-                                const gfx::Rect& rect,
-                                const gfx::Transform& draw_matrix,
-                                bool flip_vertically);
-
   bool UseScopedTexture(DrawingFrame* frame,
                         const ScopedResource* resource,
                         const gfx::Rect& viewport_rect);
diff --git a/cc/output/gl_renderer_unittest.cc b/cc/output/gl_renderer_unittest.cc
index dc68675..2af953e 100644
--- a/cc/output/gl_renderer_unittest.cc
+++ b/cc/output/gl_renderer_unittest.cc
@@ -57,8 +57,11 @@
 
 static inline SkXfermode::Mode BlendModeToSkXfermode(BlendMode blend_mode) {
   switch (blend_mode) {
+    case BlendModeNone:
     case BlendModeNormal:
       return SkXfermode::kSrcOver_Mode;
+    case BlendModeScreen:
+      return SkXfermode::kScreen_Mode;
     case BlendModeOverlay:
       return SkXfermode::kOverlay_Mode;
     case BlendModeDarken:
@@ -1421,6 +1424,7 @@
   for (int i = 0; i < NumBlendModes; ++i) {
     BlendMode blend_mode = static_cast<BlendMode>(i);
     SkXfermode::Mode xfer_mode = BlendModeToSkXfermode(blend_mode);
+    settings_.force_blending_with_shaders = (blend_mode != BlendModeNone);
     // RenderPassProgram
     render_passes_in_draw_order_.clear();
     child_pass = AddRenderPass(&render_passes_in_draw_order_,
@@ -1690,7 +1694,7 @@
 
   // If use_aa incorrectly ignores clipping, it will use the
   // RenderPassProgramAA shader instead of the RenderPassProgram.
-  TestRenderPassProgram(TexCoordPrecisionMedium, BlendModeNormal);
+  TestRenderPassProgram(TexCoordPrecisionMedium, BlendModeNone);
 }
 
 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
diff --git a/cc/output/program_binding.h b/cc/output/program_binding.h
index 722c782..a10d0ab 100644
--- a/cc/output/program_binding.h
+++ b/cc/output/program_binding.h
@@ -59,7 +59,7 @@
   void Initialize(ContextProvider* context_provider,
                   TexCoordPrecision precision,
                   SamplerType sampler,
-                  BlendMode blend_mode = BlendModeNormal) {
+                  BlendMode blend_mode = BlendModeNone) {
     DCHECK(context_provider);
     DCHECK(!initialized_);
 
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index b962d4a..e22e446 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -669,9 +669,9 @@
 }
 
 #define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect"
-#define UNUSED_BLEND_MODE_UNIFORMS (is_default_blend_mode() ? 2 : 0)
+#define UNUSED_BLEND_MODE_UNIFORMS (!has_blend_mode() ? 2 : 0)
 #define BLEND_MODE_SET_LOCATIONS(X, POS)                   \
-  if (!is_default_blend_mode()) {                          \
+  if (has_blend_mode()) {                                  \
     DCHECK_LT(static_cast<size_t>(POS) + 1, arraysize(X)); \
     backdrop_location_ = locations[POS];                   \
     backdrop_rect_location_ = locations[POS + 1];          \
@@ -680,7 +680,7 @@
 FragmentTexBlendMode::FragmentTexBlendMode()
     : backdrop_location_(-1),
       backdrop_rect_location_(-1),
-      blend_mode_(BlendModeNormal) {
+      blend_mode_(BlendModeNone) {
 }
 
 std::string FragmentTexBlendMode::SetBlendModeFunctions(
@@ -688,7 +688,7 @@
   if (shader_string.find("ApplyBlendMode") == std::string::npos)
     return shader_string;
 
-  if (is_default_blend_mode()) {
+  if (!has_blend_mode()) {
     return "#define ApplyBlendMode(X) (X)\n" + shader_string;
   }
 
@@ -902,6 +902,10 @@
 
 std::string FragmentTexBlendMode::GetBlendFunctionBodyForRGB() const {
   switch (blend_mode_) {
+    case BlendModeNormal:
+      return "result.rgb = src.rgb + dst.rgb * (1.0 - src.a);";
+    case BlendModeScreen:
+      return "result.rgb = src.rgb + (1.0 - src.rgb) * dst.rgb;";
     case BlendModeLighten:
       return "result.rgb = max((1.0 - src.a) * dst.rgb + src.rgb,"
              "                 (1.0 - dst.a) * src.rgb + dst.rgb);";
@@ -963,11 +967,11 @@
              "                           srcDstAlpha.a,"
              "                           srcDstAlpha.rgb);"
              "result.rgb += (1.0 - src.a) * dst.rgb + (1.0 - dst.a) * src.rgb;";
-    default:
+    case BlendModeNone:
+    case NumBlendModes:
       NOTREACHED();
-      // simple alpha compositing
-      return "result.rgb = src.rgb * src.a + dst.rgb * dst.a * (1 - src.a)";
   }
+  return "result = vec4(1.0, 0.0, 0.0, 1.0);";
 }
 
 FragmentTexAlphaBinding::FragmentTexAlphaBinding()
diff --git a/cc/output/shader.h b/cc/output/shader.h
index 0384366..8c1f264 100644
--- a/cc/output/shader.h
+++ b/cc/output/shader.h
@@ -39,7 +39,9 @@
 };
 
 enum BlendMode {
+  BlendModeNone,
   BlendModeNormal,
+  BlendModeScreen,
   BlendModeOverlay,
   BlendModeDarken,
   BlendModeLighten,
@@ -305,7 +307,7 @@
 
   BlendMode blend_mode() const { return blend_mode_; }
   void set_blend_mode(BlendMode blend_mode) { blend_mode_ = blend_mode; }
-  bool is_default_blend_mode() const { return blend_mode_ == BlendModeNormal; }
+  bool has_blend_mode() const { return blend_mode_ != BlendModeNone; }
 
  protected:
   FragmentTexBlendMode();
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc
index 2f0735c..cd5e890 100644
--- a/cc/resources/tile_manager_unittest.cc
+++ b/cc/resources/tile_manager_unittest.cc
@@ -149,7 +149,9 @@
 };
 
 TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueue) {
-  SetupDefaultTrees(gfx::Size(1000, 1000));
+  const gfx::Size layer_bounds(1000, 1000);
+  host_impl_.SetViewportSize(layer_bounds);
+  SetupDefaultTrees(layer_bounds);
 
   active_layer_->CreateDefaultTilingsAndTiles();
   pending_layer_->CreateDefaultTilingsAndTiles();
@@ -391,7 +393,9 @@
 }
 
 TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueue) {
-  SetupDefaultTrees(gfx::Size(1000, 1000));
+  const gfx::Size layer_bounds(1000, 1000);
+  host_impl_.SetViewportSize(layer_bounds);
+  SetupDefaultTrees(layer_bounds);
 
   active_layer_->CreateDefaultTilingsAndTiles();
   pending_layer_->CreateDefaultTilingsAndTiles();
@@ -560,6 +564,8 @@
   gfx::Size tile_size(102, 102);
   gfx::Size layer_bounds(1000, 1000);
 
+  host_impl_.SetViewportSize(layer_bounds);
+
   scoped_refptr<FakePicturePileImpl> pending_pile =
       FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
   SetupPendingTree(pending_pile);
@@ -670,7 +676,9 @@
 }
 
 TEST_F(TileManagerTilePriorityQueueTest, RasterTilePriorityQueueEmptyLayers) {
-  SetupDefaultTrees(gfx::Size(1000, 1000));
+  const gfx::Size layer_bounds(1000, 1000);
+  host_impl_.SetViewportSize(layer_bounds);
+  SetupDefaultTrees(layer_bounds);
 
   active_layer_->CreateDefaultTilingsAndTiles();
   pending_layer_->CreateDefaultTilingsAndTiles();
@@ -717,7 +725,9 @@
 }
 
 TEST_F(TileManagerTilePriorityQueueTest, EvictionTilePriorityQueueEmptyLayers) {
-  SetupDefaultTrees(gfx::Size(1000, 1000));
+  const gfx::Size layer_bounds(1000, 1000);
+  host_impl_.SetViewportSize(layer_bounds);
+  SetupDefaultTrees(layer_bounds);
 
   active_layer_->CreateDefaultTilingsAndTiles();
   pending_layer_->CreateDefaultTilingsAndTiles();
diff --git a/cc/test/data/background_filter_blur_off_axis.png b/cc/test/data/background_filter_blur_off_axis.png
index 050ec54..5077171 100644
--- a/cc/test/data/background_filter_blur_off_axis.png
+++ b/cc/test/data/background_filter_blur_off_axis.png
Binary files differ
diff --git a/cc/test/data/background_filter_blur_outsets.png b/cc/test/data/background_filter_blur_outsets.png
index 9234496..3293ab8 100644
--- a/cc/test/data/background_filter_blur_outsets.png
+++ b/cc/test/data/background_filter_blur_outsets.png
Binary files differ
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index af7eb5b..ae85fc7 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -960,7 +960,6 @@
 size_t LayerTreeHost::CalculateMemoryForRenderSurfaces(
     const RenderSurfaceLayerList& update_list) {
   size_t readback_bytes = 0;
-  size_t max_background_texture_bytes = 0;
   size_t contents_texture_bytes = 0;
 
   // Start iteration at 1 to skip the root surface as it does not have a texture
@@ -974,17 +973,16 @@
                                   RGBA_8888);
     contents_texture_bytes += bytes;
 
-    if (render_surface_layer->background_filters().IsEmpty())
+    if (render_surface_layer->background_filters().IsEmpty() &&
+        render_surface_layer->uses_default_blend_mode())
       continue;
 
-    if (bytes > max_background_texture_bytes)
-      max_background_texture_bytes = bytes;
     if (!readback_bytes) {
       readback_bytes = Resource::MemorySizeBytes(device_viewport_size_,
                                                  RGBA_8888);
     }
   }
-  return readback_bytes + max_background_texture_bytes + contents_texture_bytes;
+  return readback_bytes + contents_texture_bytes;
 }
 
 void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer,
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index fd15b52..eb90012 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -392,7 +392,7 @@
   gfx::Rect visible_rect_in_target_surface_space =
       layer->drawable_content_rect();
 
-  if (!layer->render_target()->render_surface()->clip_rect().IsEmpty()) {
+  if (layer->render_target()->render_surface()->is_clipped()) {
     // The |layer| L has a target T which owns a surface Ts. The surface Ts
     // has a target TsT.
     //
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index e0436ba..d4ded78 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -2791,6 +2791,56 @@
 }
 
 TEST_F(LayerTreeHostCommonTest,
+       VisibleContentRectsForClippedSurfaceWithEmptyClip) {
+  scoped_refptr<Layer> root = Layer::Create();
+  scoped_refptr<LayerWithForcedDrawsContent> child1 =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+  scoped_refptr<LayerWithForcedDrawsContent> child2 =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+  scoped_refptr<LayerWithForcedDrawsContent> child3 =
+      make_scoped_refptr(new LayerWithForcedDrawsContent());
+  root->AddChild(child1);
+  root->AddChild(child2);
+  root->AddChild(child3);
+
+  scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost());
+  host->SetRootLayer(root);
+
+  gfx::Transform identity_matrix;
+  SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(100, 100), true, false);
+  SetLayerPropertiesForTesting(child1.get(), identity_matrix, gfx::Point3F(),
+                               gfx::PointF(5.f, 5.f), gfx::Size(50, 50), true,
+                               false);
+  SetLayerPropertiesForTesting(child2.get(), identity_matrix, gfx::Point3F(),
+                               gfx::PointF(75.f, 75.f), gfx::Size(50, 50), true,
+                               false);
+  SetLayerPropertiesForTesting(child3.get(), identity_matrix, gfx::Point3F(),
+                               gfx::PointF(125.f, 125.f), gfx::Size(50, 50),
+                               true, false);
+
+  RenderSurfaceLayerList render_surface_layer_list;
+  // Now set the root render surface an empty clip.
+  LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
+      root.get(), gfx::Size(), &render_surface_layer_list);
+
+  LayerTreeHostCommon::CalculateDrawProperties(&inputs);
+  ASSERT_TRUE(root->render_surface());
+  EXPECT_FALSE(root->is_clipped());
+
+  gfx::Rect empty;
+  EXPECT_EQ(empty, root->render_surface()->clip_rect());
+  EXPECT_TRUE(root->render_surface()->is_clipped());
+
+  // Visible content rect calculation will check if the target surface is
+  // clipped or not. An empty clip rect does not indicate the render surface
+  // is unclipped.
+  EXPECT_EQ(empty, child1->visible_content_rect());
+  EXPECT_EQ(empty, child2->visible_content_rect());
+  EXPECT_EQ(empty, child3->visible_content_rect());
+}
+
+TEST_F(LayerTreeHostCommonTest,
        DrawableAndVisibleContentRectsForLayersWithUninvertibleTransform) {
   scoped_refptr<Layer> root = Layer::Create();
   scoped_refptr<LayerWithForcedDrawsContent> child =
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 9bee07e..e2cb1e9 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2738,10 +2738,16 @@
     }
 
     did_lock_scrolling_layer_ = true;
-    if (!allow_bubbling_for_current_layer) {
+
+    // When scrolls are allowed to bubble, it's important that the original
+    // scrolling layer be preserved. This ensures that, after a scroll bubbles,
+    // the user can reverse scroll directions and immediately resume scrolling
+    // the original layer that scrolled.
+    if (!should_bubble_scrolls_)
       active_tree_->SetCurrentlyScrollingLayer(layer_impl);
+
+    if (!allow_bubbling_for_current_layer)
       break;
-    }
 
     if (allow_unrestricted_bubbling_for_current_layer) {
       pending_delta -= applied_delta;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index adc11d0..7c0f8ab 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -7530,6 +7530,56 @@
   }
 }
 
+TEST_F(LayerTreeHostImplVirtualViewportTest,
+       TouchFlingCanLockToViewportLayerAfterBubbling) {
+  gfx::Size content_size = gfx::Size(100, 160);
+  gfx::Size outer_viewport = gfx::Size(50, 80);
+  gfx::Size inner_viewport = gfx::Size(25, 40);
+
+  SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
+
+  LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
+  LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
+
+  scoped_ptr<LayerImpl> child =
+      CreateScrollableLayer(10, outer_viewport, outer_scroll);
+  LayerImpl* child_scroll = child.get();
+  outer_scroll->children()[0]->AddChild(child.Pass());
+
+  DrawFrame();
+  {
+    scoped_ptr<ScrollAndScaleSet> scroll_info;
+
+    gfx::Vector2d scroll_delta(0, inner_viewport.height());
+    EXPECT_EQ(InputHandler::ScrollStarted,
+              host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
+    EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+
+    // The child should have scrolled up to its limit.
+    scroll_info = host_impl_->ProcessScrollDeltas();
+    ASSERT_EQ(1u, scroll_info->scrolls.size());
+    ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
+
+    // The first |ScrollBy| after the fling should re-lock the scrolling
+    // layer to the first layer that scrolled, the inner viewport scroll layer.
+    EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
+    EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
+
+    // The inner viewport should have scrolled up to its limit.
+    scroll_info = host_impl_->ProcessScrollDeltas();
+    ASSERT_EQ(2u, scroll_info->scrolls.size());
+    ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
+    ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta);
+
+    // As the locked layer is at its limit, no further scrolling can occur.
+    EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
+    EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
+    host_impl_->ScrollEnd();
+  }
+}
+
 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
  public:
   virtual void SetUp() override {
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index 7a9ef21..9b971a8b 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -52,15 +52,18 @@
 const uint32 kUseMasks = 1 << 0;
 const uint32 kUseAntialiasing = 1 << 1;
 const uint32 kUseColorMatrix = 1 << 2;
+const uint32 kForceShaders = 1 << 3;
 
 class LayerTreeHostBlendingPixelTest : public LayerTreePixelTest {
  public:
-  LayerTreeHostBlendingPixelTest() {
+  LayerTreeHostBlendingPixelTest()
+      : force_antialiasing_(false), force_blending_with_shaders_(false) {
     pixel_comparator_.reset(new FuzzyPixelOffByOneComparator(true));
   }
 
   virtual void InitializeSettings(LayerTreeSettings* settings) override {
     settings->force_antialiasing = force_antialiasing_;
+    settings->force_blending_with_shaders = force_blending_with_shaders_;
   }
 
  protected:
@@ -230,6 +233,7 @@
 
     this->impl_side_painting_ = false;
     this->force_antialiasing_ = (flags & kUseAntialiasing);
+    this->force_blending_with_shaders_ = (flags & kForceShaders);
 
     if ((flags & kUseAntialiasing) && (type == PIXEL_TEST_GL)) {
       // Anti aliasing causes differences up to 7 pixels at the edges.
@@ -279,7 +283,8 @@
     RunPixelTest(type, root, base::FilePath(expected_path));
   }
 
-  bool force_antialiasing_ = false;
+  bool force_antialiasing_;
+  bool force_blending_with_shaders_;
 };
 
 TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRoot_GL) {
@@ -433,6 +438,61 @@
       kUseMasks | kUseAntialiasing | kUseColorMatrix);
 }
 
+// Tests for render passes forcing shaders for all the blend modes.
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShaders_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass.png"),
+                            kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShadersAA_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass.png"),
+                            kUseAntialiasing | kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassShadersWithMask_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks | kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassShadersWithMaskAA_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks | kUseAntialiasing | kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassShadersColorMatrix_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass.png"),
+                            kUseColorMatrix | kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassShadersColorMatrixAA_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass.png"),
+                            kUseAntialiasing | kUseColorMatrix | kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassShadersWithMaskColorMatrix_GL) {
+  RunBlendingWithRenderPass(PIXEL_TEST_GL,
+                            FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+                            kUseMasks | kUseColorMatrix | kForceShaders);
+}
+
+TEST_F(LayerTreeHostBlendingPixelTest,
+       BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL) {
+  RunBlendingWithRenderPass(
+      PIXEL_TEST_GL, FILE_PATH_LITERAL("blending_render_pass_mask.png"),
+      kUseMasks | kUseAntialiasing | kUseColorMatrix | kForceShaders);
+}
+
 }  // namespace
 }  // namespace cc
 
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index 40fa2c3..a425eed 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -136,8 +136,8 @@
   blur->SetBackgroundFilters(filters);
 
 #if defined(OS_WIN)
-  // Windows has 153 pixels off by at most 2: crbug.com/225027
-  float percentage_pixels_large_error = 0.3825f;  // 153px / (200*200)
+  // Windows has 116 pixels off by at most 2: crbug.com/225027
+  float percentage_pixels_large_error = 0.3f;  // 116px / (200*200), rounded up
   float percentage_pixels_small_error = 0.0f;
   float average_error_allowed_in_bad_pixels = 1.f;
   int large_error_allowed = 2;
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 1d5cf1b..c9763a5 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -16,6 +16,7 @@
     : impl_side_painting(false),
       allow_antialiasing(true),
       force_antialiasing(false),
+      force_blending_with_shaders(false),
       throttle_frame_production(true),
       single_thread_proxy_scheduler(true),
       begin_frame_scheduling_enabled(false),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 74a3b0c..c5f08e9 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -21,6 +21,7 @@
   bool impl_side_painting;
   bool allow_antialiasing;
   bool force_antialiasing;
+  bool force_blending_with_shaders;
   bool throttle_frame_production;
   bool single_thread_proxy_scheduler;
   bool begin_frame_scheduling_enabled;
diff --git a/chrome/VERSION b/chrome/VERSION
index c703e46..54500b6 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=40
 MINOR=0
 BUILD=2214
-PATCH=27
+PATCH=38
diff --git a/chrome/android/java/res/color/button_tint_menu.xml b/chrome/android/java/res/color/blue_mode_tint.xml
similarity index 82%
rename from chrome/android/java/res/color/button_tint_menu.xml
rename to chrome/android/java/res/color/blue_mode_tint.xml
index b8e7fa2..b918ba4 100644
--- a/chrome/android/java/res/color/button_tint_menu.xml
+++ b/chrome/android/java/res/color/blue_mode_tint.xml
@@ -4,5 +4,5 @@
      found in the LICENSE file.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@color/default_active_button_color"/>
+    <item android:color="@color/light_active_color"/>
 </selector>
diff --git a/chrome/android/java/res/color/dark_mode_tint.xml b/chrome/android/java/res/color/dark_mode_tint.xml
new file mode 100644
index 0000000..28f2282
--- /dev/null
+++ b/chrome/android/java/res/color/dark_mode_tint.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:color="@color/light_active_color" />
+    <item android:state_focused="true" android:color="@color/light_active_color" />
+    <item android:state_pressed="true" android:color="@color/light_active_color" />
+    <item android:state_enabled="false" android:color="#335a5a5a" />
+    <item android:color="@color/light_normal_color"/>
+</selector>
diff --git a/chrome/android/java/res/color/default_button_tint.xml b/chrome/android/java/res/color/default_button_tint.xml
deleted file mode 100644
index c64c121..0000000
--- a/chrome/android/java/res/color/default_button_tint.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="true" android:color="@color/default_active_button_color" />
-    <item android:state_focused="true" android:color="@color/default_active_button_color" />
-    <item android:state_pressed="true" android:color="@color/default_active_button_color" />
-    <item android:state_enabled="false" android:color="#335a5a5a" />
-    <item android:color="@color/default_normal_button_color"/>
-</selector>
diff --git a/chrome/android/java/res/color/button_tint_white.xml b/chrome/android/java/res/color/light_mode_tint.xml
similarity index 100%
rename from chrome/android/java/res/color/button_tint_white.xml
rename to chrome/android/java/res/color/light_mode_tint.xml
diff --git a/chrome/android/java/res/layout/spinner.xml b/chrome/android/java/res/layout/spinner.xml
new file mode 100644
index 0000000..988e422
--- /dev/null
+++ b/chrome/android/java/res/layout/spinner.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<!-- A plain old Spinner.
+
+     Why is this needed? Because spinners must be inflated from a resource for the AppCompat theme
+     to work. Simply calling new Spinner() will result in a missing spinner arrow on pre-L devices.
+
+     See the FAQ on this page:
+     http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html -->
+<Spinner />
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index dc76982..f914ea5 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -7,8 +7,8 @@
 <resources>
     <!-- Common colors -->
     <color name="default_text_color">#333</color>
-    <color name="default_normal_button_color">#5A5A5A</color>
-    <color name="default_active_button_color">#4285F4</color>
+    <color name="light_normal_color">#5A5A5A</color>
+    <color name="light_active_color">#4285F4</color>
 
     <!-- Infobar colors -->
     <color name="infobar_background">#fff</color>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
index 9bf78d4..bb1bbb5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -320,7 +320,7 @@
         button.setImageDrawable(item.getIcon());
         item.getIcon().setLevel(currentLevel);
         if (item.isChecked()) {
-            button.setTint(button.getResources().getColorStateList(R.color.button_tint_menu));
+            button.setTint(button.getResources().getColorStateList(R.color.blue_mode_tint));
         }
         button.setEnabled(item.isEnabled());
         button.setFocusable(item.isEnabled());
@@ -336,7 +336,7 @@
 
     private void setupMenuButton(TintedImageButton button) {
         button.setImageResource(R.drawable.btn_menu);
-        button.setTint(button.getResources().getColorStateList(R.color.button_tint_menu));
+        button.setTint(button.getResources().getColorStateList(R.color.blue_mode_tint));
         button.setContentDescription(button.getResources().getString(R.string.menu_dismiss_btn));
         button.setEnabled(true);
         button.setFocusable(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java
index 7848fa5..77b19ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java
@@ -14,8 +14,10 @@
 import android.view.ViewTreeObserver;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.chrome.R;
 
 import java.util.ArrayList;
 
@@ -220,10 +222,13 @@
                 mTargetWrapperView.finishTransition();
                 mContainer.finishTransition();
 
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && mToShow != null &&
-                        (mAnimationType == ANIMATION_TYPE_SHOW ||
-                                mAnimationType == ANIMATION_TYPE_SWAP)) {
-                    mToShow.announceForAccessibility(mInfoBar.getMessage());
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && mToShow != null
+                        && (mAnimationType == ANIMATION_TYPE_SHOW
+                                || mAnimationType == ANIMATION_TYPE_SWAP)) {
+                    TextView messageView = (TextView) mToShow.findViewById(R.id.infobar_message);
+                    if (messageView != null) {
+                        mToShow.announceForAccessibility(messageView.getText());
+                    }
                 }
             }
         });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java
index 4162f73..f16c2f0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/GeneratedPasswordSavedInfoBar.java
@@ -13,6 +13,7 @@
  * An infobar to notify that the generated password was saved.
  */
 public class GeneratedPasswordSavedInfoBar extends InfoBar {
+    private final String mMessageText;
     private final int mInlineLinkRangeStart;
     private final int mInlineLinkRangeEnd;
     private final String mButtonLabel;
@@ -28,8 +29,9 @@
      */
     public GeneratedPasswordSavedInfoBar(long nativeInfoBar, int iconDrawableId, String messageText,
             int inlineLinkRangeStart, int inlineLinkRangeEnd, String buttonLabel) {
-        super(null, iconDrawableId, messageText);
+        super(null, iconDrawableId, null);
         setNativeInfoBar(nativeInfoBar);
+        mMessageText = messageText;
         mInlineLinkRangeStart = inlineLinkRangeStart;
         mInlineLinkRangeEnd = inlineLinkRangeEnd;
         mButtonLabel = buttonLabel;
@@ -43,7 +45,7 @@
     @Override
     public void createContent(InfoBarLayout layout) {
         layout.setButtons(mButtonLabel, null);
-        SpannableString message = new SpannableString(getMessage());
+        SpannableString message = new SpannableString(mMessageText);
         message.setSpan(
                 new ClickableSpan() {
                     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
index 829332b..36f4aad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBar.java
@@ -73,13 +73,6 @@
     }
 
     /**
-     * @return The message shown in the infobar, useful for accessibility.
-     */
-    public CharSequence getMessage() {
-        return mMessage;
-    }
-
-    /**
      * Stores a pointer to the native-side counterpart of this InfoBar.
      * @param nativeInfoBarPtr Pointer to the NativeInfoBar.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateLanguagePanel.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateLanguagePanel.java
index fb48247..77e8cb7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateLanguagePanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateLanguagePanel.java
@@ -9,6 +9,7 @@
 import android.text.SpannableString;
 import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -103,8 +104,9 @@
         mTargetAdapter.measureWidthRequiredForView();
 
         // Create the spinners.
-        mSourceSpinner = new Spinner(context);
-        mTargetSpinner = new Spinner(context);
+        LayoutInflater inflater = LayoutInflater.from(context);
+        mSourceSpinner = (Spinner) inflater.inflate(R.layout.spinner, null);
+        mTargetSpinner = (Spinner) inflater.inflate(R.layout.spinner, null);
         mSourceSpinner.setOnItemSelectedListener(this);
         mTargetSpinner.setOnItemSelectedListener(this);
         mSourceSpinner.setAdapter(mSourceAdapter);
@@ -234,8 +236,9 @@
         public View getView(int position, View convertView, ViewGroup parent) {
             TextView result;
             if (!(convertView instanceof TextView)) {
-                result = (TextView) LayoutInflater.from(getContext()).inflate(
-                        R.layout.infobar_text, null);
+                result = new TextView(getContext());
+                result.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                        getContext().getResources().getDimension(R.dimen.infobar_text_size));
             } else {
                 result = (TextView) convertView;
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
index aca80fd..934967c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
@@ -25,7 +25,7 @@
 
     public TintedDrawable(Resources res, Bitmap bitmap) {
         super(res, bitmap);
-        mTint = res.getColorStateList(R.color.default_button_tint);
+        mTint = res.getColorStateList(R.color.dark_mode_tint);
     }
 
     @Override
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index aced1b2..558629e 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -184,8 +184,8 @@
         Close
       </message>
       <!-- TranslateInfoBar -->
-      <message name="IDS_TRANSLATE_INFOBAR_TEXT" desc="Text to display on the translate infobar to offer a translate. [CHAR-LIMIT=64]">
-        This page is in <ph name="SOURCE_LANGUAGE">^1<ex>English</ex></ph>. Translate it to <ph name="TARGET_LANGUAGE">^2<ex>FRENCH</ex></ph>?
+      <message name="IDS_TRANSLATE_INFOBAR_TEXT" meaning="Android" desc="Text to display on the translate infobar to offer a translate. [CHAR-LIMIT=64]">
+        This page is in <ph name="SOURCE_LANGUAGE">^1<ex>English</ex></ph>. Translate it to <ph name="TARGET_LANGUAGE">^2<ex>French</ex></ph>?
       </message>
       <message name="IDS_TRANSLATE_INFOBAR_CHANGE_LANGUAGES" desc="link text to offer to change languages.">
         Change languages
diff --git a/chrome/android/shell/res/values-v17/styles.xml b/chrome/android/shell/res/values-v17/styles.xml
index 3d4da09..755aeff 100644
--- a/chrome/android/shell/res/values-v17/styles.xml
+++ b/chrome/android/shell/res/values-v17/styles.xml
@@ -20,7 +20,7 @@
         <item name="colorPrimaryDark">@color/material_deep_teal_500</item>
 
         <!-- Default TintedImageButton tint -->
-        <item name="tint">@color/default_button_tint</item>
+        <item name="tint">@color/dark_mode_tint</item>
     </style>
 
 </resources>
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 359d75e..80dc7fa 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -91,11 +91,11 @@
   <message name="IDS_FLAGS_ENABLE_VIDEO_PLAYER_CHROMECAST_SUPPORT_DESCRIPTION" desc="Description of the about:flag option to the enable the chromecast support for video app.">
     This option enables experimental Chromecast support for Video Player app on ChromeOS.
   </message>
-  <message name="IDS_FLAGS_DISABLE_NEW_ZIP_UNPACKER_NAME" desc="Name of about::flags option to enable the new ZIP unpacker based on the File System Provider API.">
-    Enable the new ZIP unpacker.
+  <message name="IDS_FLAGS_DISABLE_NEW_ZIP_UNPACKER_NAME" desc="Name of about::flags option to disable the new ZIP unpacker based on the File System Provider API.">
+    Disable the new ZIP unpacker.
   </message>
-  <message name="IDS_FLAGS_DISABLE_NEW_ZIP_UNPACKER_DESCRIPTION" desc="Description of about::flags option to enable the new ZIP unpacker based on the File System Provider API.">
-    Enable the new ZIP unpacker flow, based on the File System Provider API.
+  <message name="IDS_FLAGS_DISABLE_NEW_ZIP_UNPACKER_DESCRIPTION" desc="Description of about::flags option to disable the new ZIP unpacker based on the File System Provider API.">
+    Disable the new ZIP unpacker flow, based on the File System Provider API.
   </message>
   <message name="IDS_FILE_SYSTEM_PROVIDER_UNRESPONSIVE_WARNING" desc="A warning shown in a notification that an operation is taking longer than expected.">
     An operation is taking longer than expected. Do you want to abort it?
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index fd4a367..cd9c710 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6742,7 +6742,14 @@
       <message name="IDS_FLAGS_ENABLE_EASY_UNLOCK_PROXIMITY_DETECTION_DESCRIPTION" desc="Description for the flag that enables Smart Lock to require close proximity between the phone and the Chromebook in order to unlock the Chromebook.">
         Enables a Smart Lock setting that restricts unlocking to only work when your phone is very close to (roughly, within an arm's length of) the Chrome device.
       </message>
-
+      <if expr="toolkit_views">
+        <message name="IDS_FLAGS_ENABLE_LINK_DISAMBIGUATION_POPUP_NAME" desc="Title for the flag to enable the Link Disambiguation Popup, a bubble that appears over the web content screen when the user uses a touchscreen to touch a link but accidentally touches more than one link in a single gesture. The bubble appears with a zoomed-in view of the area around their touch, allowing them to more easily select the element they wanted.">
+          Enable Link Disambiguation Popup.
+        </message>
+        <message name="IDS_FLAGS_ENABLE_LINK_DISAMBIGUATION_POPUP_DESCRIPTION" desc="Description for the flag to enable the Link Disambiguation Popup, a feature on touchscreens that when enabled will cause a small zoomed popup to appear over a group of links the user has touched, allowing for selection of links on pages not yet optimized for touch input.">
+          Enable the zoomed bubble that appears on touchscreens when accidentally touching more than one link at a time.
+        </message>
+      </if>
 
       <!-- Crashes -->
       <message name="IDS_CRASHES_TITLE" desc="Title for the chrome://crashes page.">
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 6f7cd2d..b5eda1d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -941,7 +941,7 @@
     IDS_FLAGS_DISABLE_EASY_SIGNIN_NAME,
     IDS_FLAGS_DISABLE_EASY_SIGNIN_DESCRIPTION,
     kOsCrOSOwnerOnly,
-    SINGLE_VALUE_TYPE(chromeos::switches::kDisableEasySignin),
+    SINGLE_VALUE_TYPE(proximity_auth::switches::kDisableEasySignin),
   },
   {
     "enable-easy-unlock-proximity-detection",
@@ -1647,6 +1647,13 @@
     kOsCrOS | kOsWin | kOsLinux,
     SINGLE_VALUE_TYPE(views::switches::kDisableViewsRectBasedTargeting)
   },
+  {
+    "enable-link-disambiguation-popup",
+    IDS_FLAGS_ENABLE_LINK_DISAMBIGUATION_POPUP_NAME,
+    IDS_FLAGS_ENABLE_LINK_DISAMBIGUATION_POPUP_DESCRIPTION,
+    kOsCrOS | kOsWin,
+    SINGLE_VALUE_TYPE(switches::kEnableLinkDisambiguationPopup)
+  },
 #endif
 #if defined(ENABLE_EXTENSIONS)
   {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 66ccc01..aa49609 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1755,14 +1755,14 @@
 void ChromeContentBrowserClient::SelectClientCertificate(
     int render_process_id,
     int render_frame_id,
+    const net::HttpNetworkSession* network_session,
     net::SSLCertRequestInfo* cert_request_info,
     const base::Callback<void(net::X509Certificate*)>& callback) {
   content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
       render_process_id, render_frame_id);
   WebContents* tab = WebContents::FromRenderFrameHost(rfh);
   if (!tab) {
-    // TODO(davidben): This makes the request hang, but returning no certificate
-    // also breaks. It should abort the request. See https://crbug.com/417092
+    NOTREACHED();
     return;
   }
 
@@ -1808,7 +1808,8 @@
     }
   }
 
-  chrome::ShowSSLClientCertificateSelector(tab, cert_request_info, callback);
+  chrome::ShowSSLClientCertificateSelector(tab, network_session,
+                                           cert_request_info, callback);
 }
 
 void ChromeContentBrowserClient::AddCertificate(
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 93a22cc..c4fe7a6 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -172,6 +172,7 @@
   void SelectClientCertificate(
       int render_process_id,
       int render_frame_id,
+      const net::HttpNetworkSession* network_session,
       net::SSLCertRequestInfo* cert_request_info,
       const base::Callback<void(net::X509Certificate*)>& callback) override;
   void AddCertificate(net::CertificateMimeType cert_type,
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index 21ce2ef..984d131 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -1097,19 +1097,21 @@
 scoped_refptr<InputMethodManager::State> InputMethodManagerImpl::CreateNewState(
     Profile* profile) {
   StateImpl* new_state = new StateImpl(this, profile);
-#if defined(USE_ATHENA)
-  // Athena for now doesn't have user preferences for input methods,
-  // therefore no one sets the active input methods in IMF. So just set
-  // the default IME here.
-  // TODO(shuchen): we need to better initialize with user preferences.
+
+  // Active IM should be set to owner's default.
+  PrefService* prefs = g_browser_process->local_state();
+  const std::string initial_input_method_id =
+      prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout);
+
   const InputMethodDescriptor* descriptor =
       GetInputMethodUtil()->GetInputMethodDescriptorFromId(
-          GetInputMethodUtil()->GetFallbackInputMethodDescriptor().id());
+          initial_input_method_id.empty()
+              ? GetInputMethodUtil()->GetFallbackInputMethodDescriptor().id()
+              : initial_input_method_id);
   if (descriptor) {
     new_state->active_input_method_ids.push_back(descriptor->id());
     new_state->current_input_method = *descriptor;
   }
-#endif
   return scoped_refptr<InputMethodManager::State>(new_state);
 }
 
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
index 498a0c1..f8e553f 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -168,6 +168,8 @@
     mock_delegate_->set_ime_list(ime_list_);
     scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(mock_delegate_);
 
+    // CreateNewState(NULL) returns state with non-empty current_input_method.
+    // So SetState() triggers ChangeInputMethod().
     manager_->SetState(manager_->CreateNewState(NULL));
 
     std::vector<std::string> layouts;
@@ -366,12 +368,13 @@
   manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
   EXPECT_EQ(5U, manager_->GetActiveIMEState()->GetActiveInputMethods()->size());
   EXPECT_EQ(1, observer.input_method_changed_count_);
-  EXPECT_EQ(1, observer.input_method_menu_item_changed_count_);
+  // Menu change is triggered only if current input method was actually changed.
+  EXPECT_EQ(0, observer.input_method_menu_item_changed_count_);
   manager_->GetActiveIMEState()->ChangeInputMethod(
       ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */);
   EXPECT_FALSE(observer.last_show_message_);
   EXPECT_EQ(2, observer.input_method_changed_count_);
-  EXPECT_EQ(2, observer.input_method_menu_item_changed_count_);
+  EXPECT_EQ(1, observer.input_method_menu_item_changed_count_);
   manager_->GetActiveIMEState()->ChangeInputMethod(
       ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */);
   EXPECT_FALSE(observer.last_show_message_);
@@ -383,7 +386,7 @@
 
   // If the same input method ID is passed, PropertyChanged() is not
   // notified.
-  EXPECT_EQ(2, observer.input_method_menu_item_changed_count_);
+  EXPECT_EQ(1, observer.input_method_menu_item_changed_count_);
 
   manager_->RemoveObserver(&observer);
   menu_manager_->RemoveObserver(&observer);
@@ -514,8 +517,8 @@
 TEST_F(InputMethodManagerImplTest, TestEnableTwoLayouts) {
   // For http://crbug.com/19655#c11 - (8), step 6.
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
@@ -542,8 +545,8 @@
 TEST_F(InputMethodManagerImplTest, TestEnableThreeLayouts) {
   // For http://crbug.com/19655#c11 - (9).
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
@@ -575,8 +578,8 @@
 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme) {
   // For http://crbug.com/19655#c11 - (10).
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
@@ -604,8 +607,8 @@
 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme2) {
   // For http://crbug.com/19655#c11 - (11).
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
@@ -628,8 +631,8 @@
 
 TEST_F(InputMethodManagerImplTest, TestEnableImes) {
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId(kExt2Engine1Id));
@@ -644,8 +647,8 @@
 
 TEST_F(InputMethodManagerImplTest, TestEnableUnknownIds) {
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back("xkb:tl::tlh");  // Klingon, which is not supported.
@@ -662,8 +665,8 @@
 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsThenLock) {
   // For http://crbug.com/19655#c11 - (14).
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
@@ -712,8 +715,8 @@
 TEST_F(InputMethodManagerImplTest, SwitchInputMethodTest) {
   // For http://crbug.com/19655#c11 - (15).
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
@@ -764,8 +767,10 @@
 }
 
 TEST_F(InputMethodManagerImplTest, TestXkbSetting) {
+  EXPECT_EQ(0, keyboard_->set_current_keyboard_layout_by_name_count_);
   // For http://crbug.com/19655#c11 - (8), step 7-11.
   InitComponentExtension();
+  EXPECT_EQ(1, keyboard_->set_current_keyboard_layout_by_name_count_);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
@@ -774,26 +779,26 @@
   ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
   EXPECT_EQ(4U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
-  EXPECT_EQ(1, keyboard_->set_current_keyboard_layout_by_name_count_);
+  EXPECT_EQ(2, keyboard_->set_current_keyboard_layout_by_name_count_);
   // See input_methods.txt for an expected XKB layout name.
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
-  EXPECT_EQ(2, keyboard_->set_current_keyboard_layout_by_name_count_);
+  EXPECT_EQ(3, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
-  EXPECT_EQ(3, keyboard_->set_current_keyboard_layout_by_name_count_);
+  EXPECT_EQ(4, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("jp", keyboard_->last_layout_);
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
-  EXPECT_EQ(4, keyboard_->set_current_keyboard_layout_by_name_count_);
+  EXPECT_EQ(5, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("us", keyboard_->last_layout_);
   manager_->GetActiveIMEState()->SwitchToNextInputMethod();
-  EXPECT_EQ(5, keyboard_->set_current_keyboard_layout_by_name_count_);
+  EXPECT_EQ(6, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
   // Disable Dvorak.
   ids.erase(ids.begin());
   EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
   EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
-  EXPECT_EQ(6, keyboard_->set_current_keyboard_layout_by_name_count_);
+  EXPECT_EQ(7, keyboard_->set_current_keyboard_layout_by_name_count_);
   EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
 }
 
@@ -880,8 +885,8 @@
 
 TEST_F(InputMethodManagerImplTest, TestNextInputMethod) {
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   std::vector<std::string> keyboard_layouts;
   keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
   // For http://crbug.com/19655#c11 - (1)
@@ -921,8 +926,8 @@
 
 TEST_F(InputMethodManagerImplTest, TestPreviousInputMethod) {
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
 
   ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
   keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
@@ -998,8 +1003,8 @@
 TEST_F(InputMethodManagerImplTest,
        TestSwitchToPreviousInputMethodForOneActiveInputMethod) {
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
 
   ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
   keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
@@ -1024,8 +1029,8 @@
 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithUsLayouts) {
   std::string expect_id = ImeIdFromEngineId("xkb:us::eng");
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   std::vector<std::string> keyboard_layouts;
   keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
   manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
@@ -1169,8 +1174,8 @@
 
 TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) {
   TestObserver observer;
-  manager_->AddObserver(&observer);
   InitComponentExtension();
+  manager_->AddObserver(&observer);
   manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
   std::vector<std::string> ids;
   ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
index 113d372..853456b 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
@@ -18,6 +18,20 @@
 
 namespace chromeos {
 
+namespace {
+
+NetworkPortalDetector::CaptivePortalStatus GetCaptivePortalStatus() {
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  return default_network
+             ? NetworkPortalDetector::Get()
+                   ->GetCaptivePortalState(default_network->guid())
+                   .status
+             : NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN;
+}
+
+}  // namespace
+
 // static
 AutoEnrollmentCheckScreen* AutoEnrollmentCheckScreen::Get(
     ScreenManager* manager) {
@@ -33,7 +47,8 @@
       captive_portal_status_(
           NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN),
       auto_enrollment_state_(policy::AUTO_ENROLLMENT_STATE_IDLE),
-      histogram_helper_(new ErrorScreensHistogramHelper("Enrollment")) {
+      histogram_helper_(new ErrorScreensHistogramHelper("Enrollment")),
+      weak_ptr_factory_(this) {
   if (actor_)
     actor_->SetDelegate(this);
 }
@@ -44,55 +59,60 @@
     actor_->SetDelegate(NULL);
 }
 
-void AutoEnrollmentCheckScreen::Start() {
-  if (!IsStartNeeded())
-    return;
-
-  // Make sure the auto-enrollment client is running.
-  auto_enrollment_controller_->Start();
-
-  auto_enrollment_progress_subscription_ =
-      auto_enrollment_controller_->RegisterProgressCallback(
-          base::Bind(
-              &AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed,
-              base::Unretained(this)));
-  auto_enrollment_state_ = auto_enrollment_controller_->state();
-
-  // NB: AddAndFireObserver below call back into OnPortalDetectionCompleted.
-  // This guarantees that the UI gets synced to current state.
-  NetworkPortalDetector* portal_detector = NetworkPortalDetector::Get();
-  portal_detector->StartDetectionIfIdle();
-  portal_detector->AddAndFireObserver(this);
-}
-
 void AutoEnrollmentCheckScreen::ClearState() {
-   auto_enrollment_state_ = policy::AUTO_ENROLLMENT_STATE_IDLE;
-}
+  auto_enrollment_progress_subscription_.reset();
+  NetworkPortalDetector::Get()->RemoveObserver(this);
 
-bool AutoEnrollmentCheckScreen::IsStartNeeded() {
-  // Check that forced reenrollment is wanted and if the check is needed or we
-  // already know the outcome.
-  if (AutoEnrollmentController::GetMode() !=
-      AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT ||
-      auto_enrollment_state_ ==
-      policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT ||
-      auto_enrollment_state_ == policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT) {
-    SignalCompletion();
-    return false;
-  }
-  return true;
+   auto_enrollment_state_ = policy::AUTO_ENROLLMENT_STATE_IDLE;
+   captive_portal_status_ =
+       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN;
 }
 
 void AutoEnrollmentCheckScreen::PrepareToShow() {
 }
 
 void AutoEnrollmentCheckScreen::Show() {
-  if (IsStartNeeded()) {
-    Start();
-    if (actor_)
-      actor_->Show();
-    histogram_helper_->OnScreenShow();
+  // If the decision got made already, don't show the screen at all.
+  if (AutoEnrollmentController::GetMode() !=
+          AutoEnrollmentController::MODE_FORCED_RE_ENROLLMENT ||
+      IsCompleted()) {
+    SignalCompletion();
+    return;
   }
+
+  // Start from a clean slate.
+  ClearState();
+
+  // Bring up the screen. It's important to do this before updating the UI,
+  // because the latter may switch to the error screen, which needs to stay on
+  // top.
+  actor_->Show();
+  histogram_helper_->OnScreenShow();
+
+  // Set up state change observers.
+  auto_enrollment_progress_subscription_ =
+      auto_enrollment_controller_->RegisterProgressCallback(
+          base::Bind(
+              &AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed,
+              base::Unretained(this)));
+  NetworkPortalDetector* portal_detector = NetworkPortalDetector::Get();
+  portal_detector->AddObserver(this);
+
+  // Perform an initial UI update.
+  NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status =
+      GetCaptivePortalStatus();
+  policy::AutoEnrollmentState new_auto_enrollment_state =
+      auto_enrollment_controller_->state();
+
+  if (!UpdateCaptivePortalStatus(new_captive_portal_status))
+    UpdateAutoEnrollmentState(new_auto_enrollment_state);
+
+  captive_portal_status_ = new_captive_portal_status;
+  auto_enrollment_state_ = new_auto_enrollment_state;
+
+  // Make sure gears are in motion in the background.
+  auto_enrollment_controller_->Start();
+  portal_detector->StartDetectionIfIdle();
 }
 
 void AutoEnrollmentCheckScreen::Hide() {
@@ -102,11 +122,6 @@
   return WizardController::kAutoEnrollmentCheckScreenName;
 }
 
-void AutoEnrollmentCheckScreen::OnExit() {
-  get_base_screen_delegate()->OnExit(
-      BaseScreenDelegate::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
-}
-
 void AutoEnrollmentCheckScreen::OnActorDestroyed(
     AutoEnrollmentCheckScreenActor* actor) {
   if (actor_ == actor)
@@ -115,19 +130,27 @@
 
 void AutoEnrollmentCheckScreen::OnPortalDetectionCompleted(
     const NetworkState* /* network */,
-    const NetworkPortalDetector::CaptivePortalState& state) {
-  UpdateState(state.status, auto_enrollment_state_);
+    const NetworkPortalDetector::CaptivePortalState& /* state */) {
+  UpdateState();
 }
 
 void AutoEnrollmentCheckScreen::OnAutoEnrollmentCheckProgressed(
     policy::AutoEnrollmentState state) {
-  UpdateState(captive_portal_status_, state);
+  if (IsCompleted()) {
+    SignalCompletion();
+    return;
+  }
+
+  UpdateState();
 }
 
-void AutoEnrollmentCheckScreen::UpdateState(
-    NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status,
-    policy::AutoEnrollmentState new_auto_enrollment_state) {
-  // Configure the error screen to show the approriate error message.
+void AutoEnrollmentCheckScreen::UpdateState() {
+  NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status =
+      GetCaptivePortalStatus();
+  policy::AutoEnrollmentState new_auto_enrollment_state =
+      auto_enrollment_controller_->state();
+
+  // Configure the error screen to show the appropriate error message.
   if (!UpdateCaptivePortalStatus(new_captive_portal_status))
     UpdateAutoEnrollmentState(new_auto_enrollment_state);
 
@@ -146,23 +169,6 @@
   captive_portal_status_ = new_captive_portal_status;
   auto_enrollment_state_ = new_auto_enrollment_state;
 
-  // Check whether a decision got made.
-  switch (new_auto_enrollment_state) {
-    case policy::AUTO_ENROLLMENT_STATE_IDLE:
-      NOTREACHED();
-      // fall through.
-    case policy::AUTO_ENROLLMENT_STATE_PENDING:
-    case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
-      break;
-    case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
-      // Server errors don't block OOBE.
-    case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
-    case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
-      // Decision made, ready to proceed.
-      SignalCompletion();
-      return;
-  }
-
   // Retry if applicable. This is last so eventual callbacks find consistent
   // state.
   if (retry)
@@ -234,8 +240,35 @@
 void AutoEnrollmentCheckScreen::SignalCompletion() {
   NetworkPortalDetector::Get()->RemoveObserver(this);
   auto_enrollment_progress_subscription_.reset();
+
+  // Calling Finish() can cause |this| destruction, so let other methods finish
+  // their work before.
+  weak_ptr_factory_.InvalidateWeakPtrs();
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE, base::Bind(&AutoEnrollmentCheckScreen::CallOnExit,
+                            weak_ptr_factory_.GetWeakPtr()));
+}
+
+void AutoEnrollmentCheckScreen::CallOnExit() {
   get_base_screen_delegate()->OnExit(
       BaseScreenDelegate::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
 }
 
+bool AutoEnrollmentCheckScreen::IsCompleted() const {
+  switch (auto_enrollment_controller_->state()) {
+    case policy::AUTO_ENROLLMENT_STATE_IDLE:
+    case policy::AUTO_ENROLLMENT_STATE_PENDING:
+    case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
+      return false;
+    case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
+      // Server errors don't block OOBE.
+    case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
+    case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
+      // Decision made, ready to proceed.
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h
index 0eda0a3..eb38b97 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h
@@ -8,6 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h"
 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
 #include "chrome/browser/chromeos/login/screens/error_screen.h"
@@ -35,10 +36,6 @@
 
   static AutoEnrollmentCheckScreen* Get(ScreenManager* manager);
 
-  // Hands over OOBE control to this AutoEnrollmentCheckStep. It'll return the
-  // flow back to the caller via the |base_screen_delegate_|'s OnExit function.
-  void Start();
-
   // Clears the cached state causing the forced enrollment check to be retried.
   void ClearState();
 
@@ -54,7 +51,6 @@
   virtual std::string GetName() const override;
 
   // AutoEnrollmentCheckScreenActor::Delegate implementation:
-  virtual void OnExit() override;
   virtual void OnActorDestroyed(AutoEnrollmentCheckScreenActor* actor) override;
 
   // NetworkPortalDetector::Observer implementation:
@@ -67,9 +63,7 @@
   void OnAutoEnrollmentCheckProgressed(policy::AutoEnrollmentState state);
 
   // Handles a state update, updating the UI and saving the state.
-  void UpdateState(
-      NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status,
-      policy::AutoEnrollmentState new_auto_enrollment_state);
+  void UpdateState();
 
   // Configures the UI to reflect |new_captive_portal_status|. Returns true if
   // and only if a UI change has been made.
@@ -84,13 +78,16 @@
   // Configures the error screen.
   void ShowErrorScreen(ErrorScreen::ErrorState error_state);
 
-  // Signals completion. No further code should run after a call to this
-  // function as the owner might destroy |this| in response.
+  // Asynchronously signals completion. The owner might destroy |this| in
+  // response, so no code should be run after the completion of a message loop
+  // task, in which this function was called.
   void SignalCompletion();
 
-  // Checks if the enrollment status check is needed. It can be disabled either
-  // by command line flags, build configuration or might have finished already.
-  bool IsStartNeeded();
+  // Terminates the screen.
+  void CallOnExit();
+
+  // Returns whether enrollment check was completed and decision was made.
+  bool IsCompleted() const;
 
   AutoEnrollmentCheckScreenActor* actor_;
   AutoEnrollmentController* auto_enrollment_controller_;
@@ -103,6 +100,8 @@
 
   scoped_ptr<ErrorScreensHistogramHelper> histogram_helper_;
 
+  base::WeakPtrFactory<AutoEnrollmentCheckScreen> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentCheckScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h
index 22fe3ea..1079ad3 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h
@@ -16,9 +16,6 @@
    public:
     virtual ~Delegate() {}
 
-    // Called when screen is exited.
-    virtual void OnExit() = 0;
-
     // This method is called, when actor is being destroyed. Note, if Delegate
     // is destroyed earlier then it has to call SetDelegate(NULL).
     virtual void OnActorDestroyed(AutoEnrollmentCheckScreenActor* actor) = 0;
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
index 88ca35e..4da8c97 100644
--- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
@@ -150,6 +150,8 @@
 void AutoEnrollmentController::Retry() {
   if (client_)
     client_->Retry();
+  else
+    Start();
 }
 
 scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc
index c9ae41c..51a33ec 100644
--- a/chrome/browser/chromeos/login/oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -8,16 +8,12 @@
 #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"
-#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/defaults.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/chromeos_switches.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/renderer_preferences.h"
 #include "content/public/test/test_utils.h"
 #include "google_apis/gaia/fake_gaia.h"
 #include "google_apis/gaia/gaia_switches.h"
@@ -125,30 +121,4 @@
   OobeScreenWaiter(OobeDisplay::SCREEN_OOBE_ENROLLMENT).Wait();
 }
 
-IN_PROC_BROWSER_TEST_F(OobeTest, LinkDisambiguationDefaultRespected) {
-  chromeos::LoginDisplayHostImpl* display_host =
-      static_cast<chromeos::LoginDisplayHostImpl*>(
-          chromeos::LoginDisplayHostImpl::default_host());
-  ASSERT_TRUE(display_host);
-  chromeos::WebUILoginView* login_view = display_host->GetWebUILoginView();
-  ASSERT_TRUE(login_view);
-  content::WebContents* web_contents = login_view->GetWebContents();
-  ASSERT_TRUE(web_contents);
-  content::RendererPreferences* prefs = web_contents->GetMutableRendererPrefs();
-  ASSERT_TRUE(prefs);
-  // Per crbug/431163 the WiFi selection dropdown doesn't support the link
-  // disambiguation popup for gesture events, and this feature is disabled
-  // within ChromeOS. Ensure that the web preferences reflect the default.
-  if (browser_defaults::kShowLinkDisambiguationPopup) {
-    EXPECT_EQ(
-        content::TapMultipleTargetsStrategy::
-            TAP_MULTIPLE_TARGETS_STRATEGY_POPUP,
-        prefs->tap_multiple_targets_strategy);
-  } else {
-    EXPECT_EQ(
-        content::TapMultipleTargetsStrategy::TAP_MULTIPLE_TARGETS_STRATEGY_NONE,
-        prefs->tap_multiple_targets_strategy);
-  }
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 25f9f44..d1a10c3 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -216,6 +216,14 @@
   MOCK_METHOD0(Show, void());
   MOCK_METHOD0(Hide, void());
 
+  void RealShow() {
+    T::Show();
+  }
+
+  void RealHide() {
+    T::Hide();
+  }
+
  private:
   scoped_ptr<H> actor_;
 };
@@ -786,12 +794,9 @@
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
   OnExit(BaseScreenDelegate::UPDATE_INSTALLED);
 
-  AutoEnrollmentCheckScreen* screen =
-      AutoEnrollmentCheckScreen::Get(WizardController::default_controller());
-  EXPECT_EQ(screen,
-            WizardController::default_controller()->current_screen());
+  CheckCurrentScreen(WizardController::kAutoEnrollmentCheckScreenName);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
-  screen->Start();
+  mock_auto_enrollment_check_screen_->RealShow();
 
   // Wait for auto-enrollment controller to encounter the connection error.
   WaitForAutoEnrollmentState(policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR);
@@ -848,11 +853,8 @@
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
   OnExit(BaseScreenDelegate::UPDATE_INSTALLED);
 
-  AutoEnrollmentCheckScreen* screen =
-      AutoEnrollmentCheckScreen::Get(WizardController::default_controller());
-  EXPECT_EQ(screen,
-            WizardController::default_controller()->current_screen());
-  screen->Start();
+  CheckCurrentScreen(WizardController::kAutoEnrollmentCheckScreenName);
+  mock_auto_enrollment_check_screen_->RealShow();
   EXPECT_EQ(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT,
             LoginDisplayHostImpl::default_host()
                 ->GetAutoEnrollmentController()
@@ -880,12 +882,9 @@
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
   OnExit(BaseScreenDelegate::UPDATE_INSTALLED);
 
-  AutoEnrollmentCheckScreen* screen =
-      AutoEnrollmentCheckScreen::Get(WizardController::default_controller());
-  EXPECT_EQ(screen,
-            WizardController::default_controller()->current_screen());
+  CheckCurrentScreen(WizardController::kAutoEnrollmentCheckScreenName);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
-  screen->Start();
+  mock_auto_enrollment_check_screen_->RealShow();
 
   // Wait for auto-enrollment controller to encounter the connection error.
   WaitForAutoEnrollmentState(policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR);
diff --git a/chrome/browser/chromeos/net/client_cert_filter_chromeos.cc b/chrome/browser/chromeos/net/client_cert_filter_chromeos.cc
index 1ff3a78..6f735b8 100644
--- a/chrome/browser/chromeos/net/client_cert_filter_chromeos.cc
+++ b/chrome/browser/chromeos/net/client_cert_filter_chromeos.cc
@@ -26,7 +26,6 @@
   DCHECK(!init_called_);
   init_called_ = true;
 
-  init_callback_ = callback;
   if (use_system_slot_) {
     system_slot_ = crypto::GetSystemNSSKeySlot(
                        base::Bind(&ClientCertFilterChromeOS::GotSystemSlot,
@@ -38,7 +37,11 @@
                                      weak_ptr_factory_.GetWeakPtr())).Pass();
 
   // Do not call back if we initialized synchronously.
-  return InitIfSlotsAvailable();
+  if (InitIfSlotsAvailable())
+    return true;
+
+  init_callback_ = callback;
+  return false;
 }
 
 bool ClientCertFilterChromeOS::IsCertAllowed(
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index c3d2d6f..4f0903e 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -176,6 +176,9 @@
 const char kGoodExtensionCRXPath[] = "extensions/good.crx";
 const char kGoodExtensionVersion[] = "1.0";
 const char kPackagedAppCRXPath[] = "extensions/platform_apps/app_window_2.crx";
+const char kShowManagedStorageID[] = "ongnjlefhnoajpbodoldndkbkdgfomlp";
+const char kShowManagedStorageCRXPath[] = "extensions/show_managed_storage.crx";
+const char kShowManagedStorageVersion[] = "1.0";
 
 const char kExternalData[] = "External data";
 const char kExternalDataURL[] = "http://localhost/external_data";
@@ -382,6 +385,12 @@
   return user_manager::UserManager::Get()->IsSessionStarted();
 }
 
+void PolicyChangedCallback(const base::Closure& callback,
+                           const base::Value* old_value,
+                           const base::Value* new_value) {
+  callback.Run();
+}
+
 }  // namespace
 
 class DeviceLocalAccountTest : public DevicePolicyCrosBrowserTest,
@@ -1941,6 +1950,104 @@
                 .id());
 }
 
+IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, PolicyForExtensions) {
+  // Set up a test update server for the Show Managed Storage app.
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+  TestingUpdateManifestProvider testing_update_manifest_provider(
+      kRelativeUpdateURL);
+  testing_update_manifest_provider.AddUpdate(
+      kShowManagedStorageID,
+      kShowManagedStorageVersion,
+      embedded_test_server()->GetURL(std::string("/") +
+                                     kShowManagedStorageCRXPath));
+  embedded_test_server()->RegisterRequestHandler(
+      base::Bind(&TestingUpdateManifestProvider::HandleRequest,
+                 base::Unretained(&testing_update_manifest_provider)));
+
+  // Force-install the Show Managed Storage app. This app can be installed in
+  // public sessions because it's whitelisted for testing purposes.
+  em::StringList* forcelist = device_local_account_policy_.payload()
+      .mutable_extensioninstallforcelist()->mutable_value();
+  forcelist->add_entries(base::StringPrintf(
+      "%s;%s",
+      kShowManagedStorageID,
+      embedded_test_server()->GetURL(kRelativeUpdateURL).spec().c_str()));
+
+  // Set a policy for the app at the policy testserver.
+  test_server_.UpdatePolicyData(dm_protocol::kChromeExtensionPolicyType,
+                                kShowManagedStorageID,
+                                "{"
+                                "  \"string\": {"
+                                "    \"Value\": \"policy test value one\""
+                                "  }"
+                                "}");
+
+  UploadAndInstallDeviceLocalAccountPolicy();
+  AddPublicSessionToDevicePolicy(kAccountId1);
+  WaitForPolicy();
+
+  // Observe the app installation after login.
+  content::WindowedNotificationObserver extension_observer(
+      extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
+      base::Bind(DoesInstallSuccessReferToId, kShowManagedStorageID));
+  ASSERT_NO_FATAL_FAILURE(StartLogin(std::string(), std::string()));
+  WaitForSessionStart();
+  extension_observer.Wait();
+
+  // Verify that the app was installed.
+  Profile* profile = GetProfileForTest();
+  ASSERT_TRUE(profile);
+  ExtensionService* extension_service =
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  EXPECT_TRUE(extension_service->GetExtensionById(kShowManagedStorageID, true));
+
+  // Wait for the app policy if it hasn't been fetched yet.
+  ProfilePolicyConnector* connector =
+      ProfilePolicyConnectorFactory::GetForProfile(profile);
+  ASSERT_TRUE(connector);
+  PolicyService* policy_service = connector->policy_service();
+  ASSERT_TRUE(policy_service);
+  const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, kShowManagedStorageID);
+  if (policy_service->GetPolicies(ns).empty()) {
+    PolicyChangeRegistrar policy_registrar(policy_service, ns);
+    base::RunLoop run_loop;
+    policy_registrar.Observe(
+        "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
+    run_loop.Run();
+  }
+
+  // Verify that the app policy was set.
+  base::StringValue expected_value("policy test value one");
+  EXPECT_TRUE(base::Value::Equals(
+      &expected_value,
+      policy_service->GetPolicies(ns).GetValue("string")));
+
+  // Now update the policy at the server.
+  test_server_.UpdatePolicyData(dm_protocol::kChromeExtensionPolicyType,
+                                kShowManagedStorageID,
+                                "{"
+                                "  \"string\": {"
+                                "    \"Value\": \"policy test value two\""
+                                "  }"
+                                "}");
+
+  // And issue a policy refresh.
+  {
+    PolicyChangeRegistrar policy_registrar(policy_service, ns);
+    base::RunLoop run_loop;
+    policy_registrar.Observe(
+        "string", base::Bind(&PolicyChangedCallback, run_loop.QuitClosure()));
+    policy_service->RefreshPolicies(base::Closure());
+    run_loop.Run();
+  }
+
+  // Verify that the app policy was updated.
+  base::StringValue expected_new_value("policy test value two");
+  EXPECT_TRUE(base::Value::Equals(
+      &expected_new_value,
+      policy_service->GetPolicies(ns).GetValue("string")));
+}
+
 class TermsOfServiceDownloadTest : public DeviceLocalAccountTest,
                                    public testing::WithParamInterface<bool> {
 };
diff --git a/chrome/browser/chromeos/policy/device_local_account_extension_tracker.cc b/chrome/browser/chromeos/policy/device_local_account_extension_tracker.cc
index 9b86e9b..546c5bd 100644
--- a/chrome/browser/chromeos/policy/device_local_account_extension_tracker.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_extension_tracker.cc
@@ -12,6 +12,7 @@
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_namespace.h"
 #include "components/policy/core/common/schema.h"
+#include "components/policy/core/common/schema_map.h"
 #include "components/policy/core/common/schema_registry.h"
 #include "extensions/browser/pref_names.h"
 
@@ -74,6 +75,17 @@
 
   for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
     PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, it.key());
+    if (schema_registry_->schema_map()->GetSchema(ns)) {
+      // Important detail: Don't register the component again if it already
+      // has a schema! If the session already started for this public session
+      // then the real Schema for the extension has already been set by the
+      // ManagedValueStoreCache::ExtensionTracker. Do not override that schema
+      // with an invalid one now, or the policy for the extension will be
+      // dropped.
+      // However, if the forcelist is updated then we need to register the new
+      // component ID so that its remote policy data can be fetched.
+      continue;
+    }
     schema_registry_->RegisterComponent(ns, Schema());
   }
 
diff --git a/chrome/browser/chromeos/policy/device_local_account_extension_tracker.h b/chrome/browser/chromeos/policy/device_local_account_extension_tracker.h
index a357986..2b24d0a 100644
--- a/chrome/browser/chromeos/policy/device_local_account_extension_tracker.h
+++ b/chrome/browser/chromeos/policy/device_local_account_extension_tracker.h
@@ -16,6 +16,11 @@
 
 // Helper class that keeps all the extensions that a device-local account uses
 // registered in a SchemaRegistry.
+// This makes it possible to precache the policy for extensions for public
+// sessions before the session is started (e.g. during enrollment).
+// Otherwise, the ComponentCloudPolicyService would ignore the
+// PolicyFetchResponses from the DMServer because the SchemaRegistry for this
+// account doesn't have this extension "installed".
 class DeviceLocalAccountExtensionTracker : public CloudPolicyStore::Observer {
  public:
   DeviceLocalAccountExtensionTracker(
diff --git a/chrome/browser/defaults.cc b/chrome/browser/defaults.cc
index ff39b1d..6d6b6b6 100644
--- a/chrome/browser/defaults.cc
+++ b/chrome/browser/defaults.cc
@@ -16,14 +16,6 @@
 
 const int kOmniboxFontPixelSize = 16;
 
-#if defined(TOOLKIT_VIEWS)
-#if defined(OS_WIN)
-const bool kShowLinkDisambiguationPopup = true;
-#else
-const bool kShowLinkDisambiguationPopup = false;
-#endif
-#endif
-
 #if defined(OS_CHROMEOS) || defined(OS_MACOSX)
 const bool kBrowserAliveWithNoWindows = true;
 const bool kShowExitMenuItem = false;
diff --git a/chrome/browser/defaults.h b/chrome/browser/defaults.h
index 157d561..41b16d6 100644
--- a/chrome/browser/defaults.h
+++ b/chrome/browser/defaults.h
@@ -33,12 +33,6 @@
 const int kMiniTabWidth = 56;
 #endif
 
-#if defined(TOOLKIT_VIEWS)
-// Whether to show a Link Disambiguation Popup Bubble if the browser detects an
-// ambiguous touch event.
-extern const bool kShowLinkDisambiguationPopup;
-#endif
-
 // Can the browser be alive without any browser windows?
 extern const bool kBrowserAliveWithNoWindows;
 
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index b00c414..c513036 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -11,7 +11,6 @@
 
 #include "base/debug/trace_event.h"
 #include "base/lazy_instance.h"
-#include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
@@ -20,13 +19,14 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/common/extensions/api/identity.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
+#include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
@@ -845,14 +845,15 @@
     return RespondNow(Error(identity_constants::kOffTheRecord));
   }
 
+  AccountTrackerService::AccountInfo account =
+      AccountTrackerServiceFactory::GetForProfile(GetProfile())
+          ->GetAccountInfo(GetPrimaryAccountId(GetProfile()));
   api::identity::ProfileUserInfo profile_user_info;
   if (extension()->permissions_data()->HasAPIPermission(
           APIPermission::kIdentityEmail)) {
-    profile_user_info.email =
-        GetProfile()->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
+    profile_user_info.email = account.email;
   }
-  profile_user_info.id =
-      GetProfile()->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId);
+  profile_user_info.id = account.gaia;
 
   return RespondNow(OneArgument(profile_user_info.ToValue().release()));
 }
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 6d18d6b..a2881ef 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
+#include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/fake_account_reconcilor.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
@@ -33,6 +34,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/test_switches.h"
 #include "components/crx_file/id_util.h"
+#include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/common/profile_management_switches.h"
 #include "components/signin/core/common/signin_pref_names.h"
@@ -530,7 +532,70 @@
   EXPECT_TRUE(ExpectGetAccounts(only_primary));
 }
 
-class IdentityGetProfileUserInfoFunctionTest : public ExtensionBrowserTest {
+class IdentityTestWithSignin : public AsyncExtensionBrowserTest {
+ public:
+  void SetUpInProcessBrowserTestFixture() override {
+    AsyncExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
+
+    will_create_browser_context_services_subscription_ =
+        BrowserContextDependencyManager::GetInstance()
+            ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
+                  base::Bind(&IdentityTestWithSignin::
+                                 OnWillCreateBrowserContextServices,
+                             base::Unretained(this)))
+            .Pass();
+  }
+
+  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
+    // Replace the signin manager and token service with fakes. Do this ahead of
+    // creating the browser so that a bunch of classes don't register as
+    // observers and end up needing to unregister when the fake is substituted.
+    SigninManagerFactory::GetInstance()->SetTestingFactory(
+        context, &FakeSigninManagerBase::Build);
+    ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
+        context, &BuildFakeProfileOAuth2TokenService);
+    AccountReconcilorFactory::GetInstance()->SetTestingFactory(
+        context, &FakeAccountReconcilor::Build);
+  }
+
+  void SetUpOnMainThread() override {
+    AsyncExtensionBrowserTest::SetUpOnMainThread();
+
+    // Grab references to the fake signin manager and token service.
+    signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
+        SigninManagerFactory::GetInstance()->GetForProfile(profile()));
+    ASSERT_TRUE(signin_manager_);
+    token_service_ = static_cast<FakeProfileOAuth2TokenService*>(
+        ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
+            profile()));
+    ASSERT_TRUE(token_service_);
+  }
+
+ protected:
+  void SignIn(const std::string account_key) {
+#if defined(OS_CHROMEOS)
+    signin_manager_->SetAuthenticatedUsername(account_key);
+#else
+    signin_manager_->SignIn(account_key, "password");
+#endif
+    token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
+  }
+
+  void SignIn(const std::string& account_key, const std::string& gaia) {
+    AccountTrackerService* account_tracker =
+        AccountTrackerServiceFactory::GetForProfile(profile());
+    account_tracker->SeedAccountInfo(gaia, account_key);
+    SignIn(account_key);
+  }
+
+  FakeSigninManagerForTesting* signin_manager_;
+  FakeProfileOAuth2TokenService* token_service_;
+
+  scoped_ptr<base::CallbackList<void(content::BrowserContext*)>::Subscription>
+      will_create_browser_context_services_subscription_;
+};
+
+class IdentityGetProfileUserInfoFunctionTest : public IdentityTestWithSignin {
  protected:
   scoped_ptr<api::identity::ProfileUserInfo> RunGetProfileUserInfo() {
     scoped_refptr<IdentityGetProfileUserInfoFunction> func(
@@ -568,11 +633,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, SignedIn) {
-  profile()->GetPrefs()
-      ->SetString(prefs::kGoogleServicesUsername, "president@example.com");
-  profile()->GetPrefs()
-      ->SetString(prefs::kGoogleServicesUserAccountId, "12345");
-
+  SignIn("president@example.com", "12345");
   scoped_ptr<api::identity::ProfileUserInfo> info =
       RunGetProfileUserInfoWithEmail();
   EXPECT_EQ("president@example.com", info->email);
@@ -588,69 +649,19 @@
 
 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
                        SignedInNoEmail) {
-  profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                   "president@example.com");
-  profile()->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId,
-                                   "12345");
-
+  SignIn("president@example.com", "12345");
   scoped_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
   EXPECT_TRUE(info->email.empty());
   EXPECT_EQ("12345", info->id);
 }
 
-class GetAuthTokenFunctionTest : public AsyncExtensionBrowserTest {
+class GetAuthTokenFunctionTest : public IdentityTestWithSignin {
  public:
   void SetUpCommandLine(CommandLine* command_line) override {
-    AsyncExtensionBrowserTest::SetUpCommandLine(command_line);
+    IdentityTestWithSignin::SetUpCommandLine(command_line);
     command_line->AppendSwitch(switches::kExtensionsMultiAccount);
   }
 
-  void SetUpInProcessBrowserTestFixture() override {
-    AsyncExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
-
-    will_create_browser_context_services_subscription_ =
-        BrowserContextDependencyManager::GetInstance()
-            ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
-                  base::Bind(&GetAuthTokenFunctionTest::
-                                 OnWillCreateBrowserContextServices,
-                             base::Unretained(this)))
-            .Pass();
-  }
-
-  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
-    // Replace the signin manager and token service with fakes. Do this ahead of
-    // creating the browser so that a bunch of classes don't register as
-    // observers and end up needing to unregister when the fake is substituted.
-    SigninManagerFactory::GetInstance()->SetTestingFactory(
-        context, &FakeSigninManagerBase::Build);
-    ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
-        context, &BuildFakeProfileOAuth2TokenService);
-    AccountReconcilorFactory::GetInstance()->SetTestingFactory(
-        context, &FakeAccountReconcilor::Build);
-  }
-
-  void SetUpOnMainThread() override {
-    AsyncExtensionBrowserTest::SetUpOnMainThread();
-
-    // Grab references to the fake signin manager and token service.
-    signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
-        SigninManagerFactory::GetInstance()->GetForProfile(profile()));
-    ASSERT_TRUE(signin_manager_);
-    token_service_ = static_cast<FakeProfileOAuth2TokenService*>(
-        ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
-            profile()));
-    ASSERT_TRUE(token_service_);
-  }
-
-  void SignIn(const std::string account_key) {
-#if defined(OS_CHROMEOS)
-    signin_manager_->SetAuthenticatedUsername(account_key);
-#else
-    signin_manager_->SignIn(account_key, "password");
-#endif
-    token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
-  }
-
   void IssueLoginRefreshTokenForAccount(const std::string account_key) {
     token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
   }
@@ -675,9 +686,6 @@
     AS_COMPONENT = 4
   };
 
-  FakeSigninManagerForTesting* signin_manager_;
-  FakeProfileOAuth2TokenService* token_service_;
-
   ~GetAuthTokenFunctionTest() override {}
 
   // Helper to create an extension with specific OAuth2Info fields set.
@@ -744,9 +752,6 @@
  private:
   std::string extension_id_;
   std::set<std::string> oauth_scopes_;
-
-  scoped_ptr<base::CallbackList<void(content::BrowserContext*)>::Subscription>
-      will_create_browser_context_services_subscription_;
 };
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
index e334630..9e7e94c 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h"
 
 #include "base/json/json_string_value_serializer.h"
+#include "base/prefs/pref_service.h"
 #include "base/sys_info.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -13,6 +14,7 @@
 #include "chrome/browser/sync/about_sync_util.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/common/chrome_version_info.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
@@ -23,6 +25,7 @@
 
 const char kSyncDataKey[] = "about_sync_data";
 const char kExtensionsListKey[] = "extensions";
+const char kDataReductionProxyKey[] = "data_reduction_proxy";
 const char kChromeVersionTag[] = "CHROME VERSION";
 #if !defined(OS_CHROMEOS)
 const char kOsVersionTag[] = "OS VERSION";
@@ -57,6 +60,7 @@
 
   PopulateSyncLogs(&response);
   PopulateExtensionInfoLogs(&response);
+  PopulateDataReductionProxyLogs(&response);
 
   callback.Run(&response);
 }
@@ -133,4 +137,15 @@
     (*response)[kExtensionsListKey] = extensions_list;
 }
 
+void ChromeInternalLogSource::PopulateDataReductionProxyLogs(
+    SystemLogsResponse* response) {
+  PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
+  bool is_data_reduction_proxy_enabled = prefs->HasPrefPath(
+          data_reduction_proxy::prefs::kDataReductionProxyEnabled) &&
+      prefs->GetBoolean(
+          data_reduction_proxy::prefs::kDataReductionProxyEnabled);
+  (*response)[kDataReductionProxyKey] = is_data_reduction_proxy_enabled ?
+      "enabled" : "disabled";
+}
+
 }  // namespace system_logs
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
index f533965..a4a7c61 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h
@@ -21,6 +21,7 @@
  private:
   void PopulateSyncLogs(SystemLogsResponse* response);
   void PopulateExtensionInfoLogs(SystemLogsResponse* response);
+  void PopulateDataReductionProxyLogs(SystemLogsResponse* response);
 
   DISALLOW_COPY_AND_ASSIGN(ChromeInternalLogSource);
 };
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index fc0ada5..bf1e2e0 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -22,7 +22,6 @@
 #endif
 
 #if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/defaults.h"
 #include "ui/views/controls/textfield/textfield.h"
 #endif
 
@@ -70,14 +69,6 @@
 
 #if defined(TOOLKIT_VIEWS)
   prefs->caret_blink_interval = views::Textfield::GetCaretBlinkMs() / 1000.0;
-  if (browser_defaults::kShowLinkDisambiguationPopup) {
-    prefs->tap_multiple_targets_strategy =
-        content::TapMultipleTargetsStrategy::
-            TAP_MULTIPLE_TARGETS_STRATEGY_POPUP;
-  } else {
-    prefs->tap_multiple_targets_strategy =
-        content::TapMultipleTargetsStrategy::TAP_MULTIPLE_TARGETS_STRATEGY_NONE;
-  }
 #endif
 
 #if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
diff --git a/chrome/browser/resources/easy_unlock/manifest.json b/chrome/browser/resources/easy_unlock/manifest.json
index 9c56540..b4e6a59 100644
--- a/chrome/browser/resources/easy_unlock/manifest.json
+++ b/chrome/browser/resources/easy_unlock/manifest.json
@@ -1,6 +1,6 @@
 {
-  "name": "Easy Unlock",
-  "description": "This app sets up unlocking the device with a phone.",
+  "name": "Smart Lock",
+  "description": "This app allows you to unlock your device when in proximity to your phone.",
   "version": "1.0",
   "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqOUeUl1nC6qTz6WwVUIaAJ4ukXVzgeCAumX4TZlCHFk5DLHImHLDBxakyVGaQFLS9iEQ3tDTsJLIoA+FkbWKNX7bvDW/qM89CeVNZsIZRGw898m8J78N6dJHwP9aZSI8CpoMK2KvjANpuj1tdWs1OM6v65zRUu6y4Mq876dr5AcPiuznGxl8jekagBwGu8jqMySsJxLazj/EfQ3W1E7mpyHd0Z4C1qNwJoFlUQeMjn6gfPZqa06BLU6YznzCUesiyjFK3d1vzbN54ZkVxhcA6ekwLKYLqKykBFLmIQG0gkNNePzcGXju8p34dGJgkcZw0sOXrtNaLSe1su0zfcniIwIDAQAB",
 
diff --git a/chrome/browser/resources/gaia_auth/main.js b/chrome/browser/resources/gaia_auth/main.js
index 7523ceb..05271fb 100644
--- a/chrome/browser/resources/gaia_auth/main.js
+++ b/chrome/browser/resources/gaia_auth/main.js
@@ -351,9 +351,16 @@
    */
   onCompleteLogin_: function(msg) {
     if (!msg.email || !msg.gaiaId || !msg.sessionIndex) {
-      console.error('Missing fields to complete login.');
-      window.parent.postMessage({method: 'missingGaiaInfo'}, this.parentPage_);
-      return;
+      // On desktop, if the skipForNow message field is set, send it to handler.
+      // This does not require the email, gaiaid or session to be valid.
+      if (this.desktopMode_ && msg.skipForNow) {
+        this.completeLogin_(msg);
+      } else {
+        console.error('Missing fields to complete login.');
+        window.parent.postMessage({method: 'missingGaiaInfo'},
+                                  this.parentPage_);
+        return;
+      }
     }
 
     // Skip SAML extra steps for desktop flow and non-SAML flow.
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 30f2523..c8f2e7f 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -312,6 +312,7 @@
       switch (reason) {
         case REASON_EMPTY_URL_CHAIN:
         case REASON_INVALID_URL:
+        case REASON_UNSUPPORTED_URL_SCHEME:
           PostFinishTask(UNKNOWN, reason);
           return;
 
@@ -462,11 +463,15 @@
       return false;
     }
     const GURL& final_url = item.GetUrlChain().back();
-    if (!final_url.is_valid() || final_url.is_empty() ||
-        !final_url.IsStandard() || final_url.SchemeIsFile()) {
+    if (!final_url.is_valid() || final_url.is_empty()) {
       *reason = REASON_INVALID_URL;
       return false;
     }
+    if ((!final_url.IsStandard() && !final_url.SchemeIsBlob()) ||
+        final_url.SchemeIsFile()) {
+      *reason = REASON_UNSUPPORTED_URL_SCHEME;
+      return false;
+    }
     if (!download_protection_util::IsBinaryFile(target_path)) {
       *reason = REASON_NOT_BINARY_FILE;
       return false;
diff --git a/chrome/browser/safe_browsing/download_protection_service.h b/chrome/browser/safe_browsing/download_protection_service.h
index a42addd..603ce8d 100644
--- a/chrome/browser/safe_browsing/download_protection_service.h
+++ b/chrome/browser/safe_browsing/download_protection_service.h
@@ -157,6 +157,7 @@
     REASON_ARCHIVE_WITHOUT_BINARIES,
     REASON_DOWNLOAD_DANGEROUS_HOST,
     REASON_DOWNLOAD_POTENTIALLY_UNWANTED,
+    REASON_UNSUPPORTED_URL_SCHEME,
     REASON_MAX  // Always add new values before this one.
   };
 
@@ -172,6 +173,8 @@
   FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
                            CheckClientDownloadHTTPS);
   FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
+                           CheckClientDownloadBlob);
+  FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
                            CheckClientDownloadZip);
   FRIEND_TEST_ALL_PREFIXES(DownloadProtectionServiceTest,
                            CheckClientDownloadFetchFailed);
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index 84fd01d..fca1671 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -872,6 +872,62 @@
 #endif
 }
 
+TEST_F(DownloadProtectionServiceTest, CheckClientDownloadBlob) {
+  ClientDownloadResponse response;
+  response.set_verdict(ClientDownloadResponse::DANGEROUS);
+  net::FakeURLFetcherFactory factory(NULL);
+  factory.SetFakeResponse(DownloadProtectionService::GetDownloadRequestUrl(),
+                          response.SerializeAsString(), net::HTTP_OK,
+                          net::URLRequestStatus::SUCCESS);
+
+  base::FilePath a_tmp(FILE_PATH_LITERAL("a.tmp"));
+  base::FilePath a_exe(FILE_PATH_LITERAL("a.exe"));
+  std::vector<GURL> url_chain;
+  url_chain.push_back(
+      GURL("blob:http://www.evil.com/50b85f60-71e4-11e4-82f8-0800200c9a66"));
+  GURL referrer("http://www.google.com/");
+  std::string hash = "hash";
+
+  content::MockDownloadItem item;
+  EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(a_tmp));
+  EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
+  EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
+  EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
+  EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
+  EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
+  EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
+
+  EXPECT_CALL(*sb_service_->mock_database_manager(),
+              MatchDownloadWhitelistUrl(_)).WillRepeatedly(Return(false));
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
+      .Times(1);
+  EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
+      .Times(1);
+
+  download_service_->CheckClientDownload(
+      &item,
+      base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
+                 base::Unretained(this)));
+  MessageLoop::current()->Run();
+#if defined(OS_WIN)
+  EXPECT_TRUE(IsResult(DownloadProtectionService::DANGEROUS));
+#else
+  EXPECT_TRUE(IsResult(DownloadProtectionService::UNKNOWN));
+#endif
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+  // OSX sends pings for evaluation purposes.
+  EXPECT_TRUE(HasClientDownloadRequest());
+  ClearClientDownloadRequest();
+#else
+  EXPECT_FALSE(HasClientDownloadRequest());
+#endif
+}
+
 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadZip) {
   ClientDownloadResponse response;
   response.set_verdict(ClientDownloadResponse::SAFE);
diff --git a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
index 6a6acd0..d8bbb5d 100644
--- a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.cc
@@ -587,17 +587,19 @@
     if (iter != pending_items_.end()) {
       const ItemData& item_data = iter->second;
       download = item_data.item;  // non-null if not destroyed.
-      if (item_data.removed)
+      if (item_data.removed) {
         RemoveMetadata();
-      else if (!item_data.last_opened_time.is_null())
+        download = nullptr;
+      } else if (!item_data.last_opened_time.is_null()) {
         UpdateLastOpenedTime(item_data.last_opened_time);
+      }
     }
   }
 
   // Stop observing all items.
   ClearPendingItems();
 
-  // If the download was known, observe it from here on out.
+  // If the download was known and not removed, observe it from here on out.
   if (download) {
     download->AddObserver(this);
     item_ = download;
diff --git a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc
index 538a7da..c722923 100644
--- a/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/download_metadata_manager_unittest.cc
@@ -307,6 +307,10 @@
   if (details_loaded_)
     RunAllTasks();
 
+  // In http://crbug.com/433928, open after removal during load caused a crash.
+  if (item_action_ == REMOVED)
+    test_item_->NotifyObserversDownloadOpened();
+
   MockDownloadDetailsGetter details_getter;
   if (metadata_file_present_ && item_action_ != REMOVED) {
     // The file is present, so expect that the callback is invoked with the
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc
index 9281513..93a25a4 100644
--- a/chrome/browser/signin/easy_unlock_service.cc
+++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/metrics/field_trial.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
@@ -27,6 +26,7 @@
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
 #include "components/pref_registry/pref_registry_syncable.h"
+#include "components/proximity_auth/switches.h"
 #include "components/user_manager/user.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -81,19 +81,8 @@
 
 // static
 bool EasyUnlockService::IsSignInEnabled() {
-#if defined(OS_CHROMEOS)
-  const std::string group_name =
-      base::FieldTrialList::FindFullName("EasySignIn");
-
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kDisableEasySignin)) {
-    return false;
-  }
-
-  return group_name == "Enable";
-#else
-  return false;
-#endif
+  return !CommandLine::ForCurrentProcess()->HasSwitch(
+      proximity_auth::switches::kDisableEasySignin);
 }
 
 class EasyUnlockService::BluetoothDetector
@@ -246,6 +235,11 @@
   if (shut_down_)
     return false;
 
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          proximity_auth::switches::kDisableEasyUnlock)) {
+    return false;
+  }
+
   if (!IsAllowedInternal())
     return false;
 
diff --git a/chrome/browser/signin/easy_unlock_service_browsertest_chromeos.cc b/chrome/browser/signin/easy_unlock_service_browsertest_chromeos.cc
index 10f5f07..e68a27c 100644
--- a/chrome/browser/signin/easy_unlock_service_browsertest_chromeos.cc
+++ b/chrome/browser/signin/easy_unlock_service_browsertest_chromeos.cc
@@ -22,6 +22,7 @@
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
+#include "components/proximity_auth/switches.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/common/content_switches.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -136,11 +137,41 @@
   DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceTest);
 };
 
-IN_PROC_BROWSER_TEST_F(EasyUnlockServiceTest, NoFinchNoService) {
+IN_PROC_BROWSER_TEST_F(EasyUnlockServiceTest, DefaultOn) {
+  EXPECT_TRUE(service()->IsAllowed());
+#if defined(GOOGLE_CHROME_BUILD)
+  EXPECT_TRUE(HasEasyUnlockApp());
+#endif
+}
+
+#if defined(GOOGLE_CHROME_BUILD)
+IN_PROC_BROWSER_TEST_F(EasyUnlockServiceTest, UnloadsOnSuspend) {
+  EXPECT_TRUE(HasEasyUnlockApp());
+  power_manager_client()->SendSuspendImminent();
+  EXPECT_FALSE(HasEasyUnlockApp());
+  power_manager_client()->SendSuspendDone();
+  EXPECT_TRUE(HasEasyUnlockApp());
+}
+#endif
+
+IN_PROC_BROWSER_TEST_F(EasyUnlockServiceTest, PolicyOveride) {
+  EXPECT_TRUE(service()->IsAllowed());
+#if defined(GOOGLE_CHROME_BUILD)
+  EXPECT_TRUE(HasEasyUnlockApp());
+#endif
+
+  // Overridden by policy.
+  SetEasyUnlockAllowedPolicy(false);
   EXPECT_FALSE(service()->IsAllowed());
 #if defined(GOOGLE_CHROME_BUILD)
   EXPECT_FALSE(HasEasyUnlockApp());
 #endif
+
+  SetEasyUnlockAllowedPolicy(true);
+  EXPECT_TRUE(service()->IsAllowed());
+#if defined(GOOGLE_CHROME_BUILD)
+  EXPECT_TRUE(HasEasyUnlockApp());
+#endif
 }
 
 class EasyUnlockServiceNoBluetoothTest : public EasyUnlockServiceTest {
@@ -165,78 +196,29 @@
 #endif
 }
 
-class EasyUnlockServiceFinchEnabledTest : public EasyUnlockServiceTest {
+class EasyUnlockServiceDisabledTest : public EasyUnlockServiceTest {
  public:
-  EasyUnlockServiceFinchEnabledTest() {}
-  virtual ~EasyUnlockServiceFinchEnabledTest() {}
+  EasyUnlockServiceDisabledTest() {}
+  virtual ~EasyUnlockServiceDisabledTest() {}
 
   // InProcessBrowserTest:
   virtual void SetUpCommandLine(CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
-                                    "EasyUnlock/Enable/");
+    command_line->AppendSwitch(proximity_auth::switches::kDisableEasyUnlock);
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceFinchEnabledTest);
+  DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceDisabledTest);
 };
 
-IN_PROC_BROWSER_TEST_F(EasyUnlockServiceFinchEnabledTest, Enabled) {
-  EXPECT_TRUE(service()->IsAllowed());
-#if defined(GOOGLE_CHROME_BUILD)
-  EXPECT_TRUE(HasEasyUnlockApp());
-#endif
-}
-
-#if defined(GOOGLE_CHROME_BUILD)
-IN_PROC_BROWSER_TEST_F(EasyUnlockServiceFinchEnabledTest, UnloadsOnSuspend) {
-  EXPECT_TRUE(HasEasyUnlockApp());
-  power_manager_client()->SendSuspendImminent();
-  EXPECT_FALSE(HasEasyUnlockApp());
-  power_manager_client()->SendSuspendDone();
-  EXPECT_TRUE(HasEasyUnlockApp());
-}
-#endif
-
-// Tests that policy can override finch to turn easy unlock off.
-IN_PROC_BROWSER_TEST_F(EasyUnlockServiceFinchEnabledTest, PolicyOveride) {
-  EXPECT_TRUE(service()->IsAllowed());
-#if defined(GOOGLE_CHROME_BUILD)
-  EXPECT_TRUE(HasEasyUnlockApp());
-#endif
-
-  // Overridden by policy.
-  SetEasyUnlockAllowedPolicy(false);
+IN_PROC_BROWSER_TEST_F(EasyUnlockServiceDisabledTest, Disabled) {
   EXPECT_FALSE(service()->IsAllowed());
 #if defined(GOOGLE_CHROME_BUILD)
   EXPECT_FALSE(HasEasyUnlockApp());
 #endif
-
-  SetEasyUnlockAllowedPolicy(true);
-  EXPECT_TRUE(service()->IsAllowed());
-#if defined(GOOGLE_CHROME_BUILD)
-  EXPECT_TRUE(HasEasyUnlockApp());
-#endif
 }
 
-class EasyUnlockServiceFinchDisabledTest : public EasyUnlockServiceTest {
- public:
-  EasyUnlockServiceFinchDisabledTest() {}
-  virtual ~EasyUnlockServiceFinchDisabledTest() {}
-
-  // InProcessBrowserTest:
-  virtual void SetUpCommandLine(CommandLine* command_line) override {
-    command_line->AppendSwitchASCII(switches::kForceFieldTrials,
-                                    "EasyUnlock/Disable/");
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceFinchDisabledTest);
-};
-
-// Tests that easy unlock is off when finch is disabled and policy overrides
-// finch.
-IN_PROC_BROWSER_TEST_F(EasyUnlockServiceFinchDisabledTest, PolicyOverride) {
-  // Finch is disabled.
+// Tests that policy does not override disabled switch.
+IN_PROC_BROWSER_TEST_F(EasyUnlockServiceDisabledTest, NoPolicyOverride) {
   EXPECT_FALSE(service()->IsAllowed());
 #if defined(GOOGLE_CHROME_BUILD)
   EXPECT_FALSE(HasEasyUnlockApp());
@@ -244,9 +226,9 @@
 
   // Policy overrides finch and turns on Easy unlock.
   SetEasyUnlockAllowedPolicy(true);
-  EXPECT_TRUE(service()->IsAllowed());
+  EXPECT_FALSE(service()->IsAllowed());
 #if defined(GOOGLE_CHROME_BUILD)
-  EXPECT_TRUE(HasEasyUnlockApp());
+  EXPECT_FALSE(HasEasyUnlockApp());
 #endif
 }
 
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc
index fb027f3..1eca98e 100644
--- a/chrome/browser/signin/easy_unlock_service_regular.cc
+++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "base/metrics/field_trial.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
 #include "base/values.h"
@@ -279,12 +278,6 @@
   if (!profile()->GetPrefs()->GetBoolean(prefs::kEasyUnlockAllowed))
     return false;
 
-  // Respect existing policy and skip finch test.
-  if (!profile()->GetPrefs()->IsManagedPreference(prefs::kEasyUnlockAllowed)) {
-    // It is enabled when the trial exists and is in "Enable" group.
-    return base::FieldTrialList::FindFullName("EasyUnlock") == "Enable";
-  }
-
   return true;
 #else
   // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
index ec49823..0a3dd4f 100644
--- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
+++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -9,6 +9,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "base/sys_info.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
@@ -184,7 +185,9 @@
 
 void EasyUnlockServiceSignin::RecordPasswordLoginEvent(
     const std::string& user_id) const {
-  DCHECK_EQ(GetUserEmail(), user_id);
+  // This happens during tests where user could login without pod focusing.
+  if (GetUserEmail() != user_id)
+    return;
 
   chromeos::EasyUnlockLoginEvent event =
       chromeos::EASY_SIGN_IN_LOGIN_EVENT_COUNT;
@@ -310,6 +313,10 @@
 }
 
 void EasyUnlockServiceSignin::LoadCurrentUserDataIfNeeded() {
+  // TODO(xiyuan): Revisit this when adding tests.
+  if (!base::SysInfo::IsRunningOnChromeOS())
+    return;
+
   if (user_id_.empty() || !service_active_)
     return;
 
diff --git a/chrome/browser/ssl/ssl_client_auth_observer.cc b/chrome/browser/ssl/ssl_client_auth_observer.cc
index edc63bb..46f580e 100644
--- a/chrome/browser/ssl/ssl_client_auth_observer.cc
+++ b/chrome/browser/ssl/ssl_client_auth_observer.cc
@@ -19,10 +19,10 @@
 typedef std::pair<net::SSLCertRequestInfo*, net::X509Certificate*> CertDetails;
 
 SSLClientAuthObserver::SSLClientAuthObserver(
-    const content::BrowserContext* browser_context,
+    const net::HttpNetworkSession* network_session,
     const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
     const base::Callback<void(net::X509Certificate*)>& callback)
-    : browser_context_(browser_context),
+    : network_session_(network_session),
       cert_request_info_(cert_request_info),
       callback_(callback) {
 }
@@ -44,7 +44,7 @@
   content::NotificationService* service =
       content::NotificationService::current();
   service->Notify(chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED,
-                  content::Source<content::BrowserContext>(browser_context_),
+                  content::Source<net::HttpNetworkSession>(network_session_),
                   content::Details<CertDetails>(&details));
 
   callback_.Run(certificate);
@@ -76,7 +76,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   notification_registrar_.Add(
       this, chrome::NOTIFICATION_SSL_CLIENT_AUTH_CERT_SELECTED,
-      content::Source<content::BrowserContext>(browser_context_));
+      content::Source<net::HttpNetworkSession>(network_session_));
 }
 
 void SSLClientAuthObserver::StopObserving() {
diff --git a/chrome/browser/ssl/ssl_client_auth_observer.h b/chrome/browser/ssl/ssl_client_auth_observer.h
index 62e3fde..1fe5f39 100644
--- a/chrome/browser/ssl/ssl_client_auth_observer.h
+++ b/chrome/browser/ssl/ssl_client_auth_observer.h
@@ -11,18 +11,15 @@
 #include "content/public/browser/notification_registrar.h"
 
 namespace net {
+class HttpNetworkSession;
 class SSLCertRequestInfo;
 class X509Certificate;
 }
 
-namespace content {
-class BrowserContext;
-}
-
 class SSLClientAuthObserver : public content::NotificationObserver {
  public:
   SSLClientAuthObserver(
-      const content::BrowserContext* browser_context,
+      const net::HttpNetworkSession* network_session,
       const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
       const base::Callback<void(net::X509Certificate*)>& callback);
   ~SSLClientAuthObserver() override;
@@ -55,7 +52,7 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  const content::BrowserContext* browser_context_;
+  const net::HttpNetworkSession* network_session_;
   scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
   base::Callback<void(net::X509Certificate*)> callback_;
   content::NotificationRegistrar notification_registrar_;
diff --git a/chrome/browser/ssl/ssl_client_auth_requestor_mock.cc b/chrome/browser/ssl/ssl_client_auth_requestor_mock.cc
index 6f63c32..78c2c96 100644
--- a/chrome/browser/ssl/ssl_client_auth_requestor_mock.cc
+++ b/chrome/browser/ssl/ssl_client_auth_requestor_mock.cc
@@ -4,13 +4,18 @@
 
 #include "chrome/browser/ssl/ssl_client_auth_requestor_mock.h"
 
+#include "net/http/http_transaction_factory.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
 
 SSLClientAuthRequestorMock::SSLClientAuthRequestorMock(
     net::URLRequest* request,
     const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info)
-    : cert_request_info_(cert_request_info) {
+    : cert_request_info_(cert_request_info),
+      http_network_session_(request->context()
+                                ->http_transaction_factory()
+                                ->GetSession()) {
 }
 
 SSLClientAuthRequestorMock::~SSLClientAuthRequestorMock() {}
diff --git a/chrome/browser/ssl/ssl_client_auth_requestor_mock.h b/chrome/browser/ssl/ssl_client_auth_requestor_mock.h
index 7d63a7c..69bd729 100644
--- a/chrome/browser/ssl/ssl_client_auth_requestor_mock.h
+++ b/chrome/browser/ssl/ssl_client_auth_requestor_mock.h
@@ -25,6 +25,7 @@
   MOCK_METHOD1(CertificateSelected, void(net::X509Certificate* cert));
 
   scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
+  net::HttpNetworkSession* http_network_session_;
 
  protected:
   friend class base::RefCountedThreadSafe<SSLClientAuthRequestorMock>;
diff --git a/chrome/browser/ssl/ssl_client_certificate_selector.h b/chrome/browser/ssl/ssl_client_certificate_selector.h
index 1a33c05..afec4ad 100644
--- a/chrome/browser/ssl/ssl_client_certificate_selector.h
+++ b/chrome/browser/ssl/ssl_client_certificate_selector.h
@@ -12,6 +12,7 @@
 }
 
 namespace net {
+class HttpNetworkSession;
 class SSLCertRequestInfo;
 class X509Certificate;
 }
@@ -27,6 +28,7 @@
 // with a NULL certificate.
 void ShowSSLClientCertificateSelector(
     content::WebContents* contents,
+    const net::HttpNetworkSession* network_session,
     net::SSLCertRequestInfo* cert_request_info,
     const SelectCertificateCallback& callback);
 
diff --git a/chrome/browser/ui/android/ssl_client_certificate_request.cc b/chrome/browser/ui/android/ssl_client_certificate_request.cc
index 65c9ada..afe2d7e 100644
--- a/chrome/browser/ui/android/ssl_client_certificate_request.cc
+++ b/chrome/browser/ui/android/ssl_client_certificate_request.cc
@@ -226,6 +226,7 @@
 
 void ShowSSLClientCertificateSelector(
     content::WebContents* contents,
+    const net::HttpNetworkSession* network_session,
     net::SSLCertRequestInfo* cert_request_info,
     const chrome::SelectCertificateCallback& callback) {
   ui::WindowAndroid* window =
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm
index 514ce33..0a2fda5 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_container_view.mm
@@ -124,7 +124,7 @@
       (NSWidth(containerFrame) < maxWidth_);
 
   // Notify others to see whether this dragging is allowed.
-  if (canDragLeft_ || canDragRight_) {
+  if ((dX < 0.0 && canDragLeft_) || (dX > 0.0 && canDragRight_)) {
     NSDictionary* userInfo = @{ kTranslationWithDelta : @(dX) };
     [[NSNotificationCenter defaultCenter]
         postNotificationName:kBrowserActionGrippyWillDragNotification
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
index aacdafe..991a23a 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.h
@@ -16,10 +16,6 @@
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h"
 
-namespace content {
-class BrowserContext;
-}
-
 class ConstrainedWindowMac;
 @class SFChooseIdentityPanel;
 class SSLClientAuthObserverCocoaBridge;
@@ -45,7 +41,7 @@
 
 @property (readonly, nonatomic) SFChooseIdentityPanel* panel;
 
-- (id)initWithBrowserContext:(const content::BrowserContext*)browserContext
+- (id)initWithNetworkSession:(const net::HttpNetworkSession*)networkSession
              certRequestInfo:(net::SSLCertRequestInfo*)certRequestInfo
                     callback:(const chrome::SelectCertificateCallback&)callback;
 - (void)displayForWebContents:(content::WebContents*)webContents;
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
index 9d471b9..027b896 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
@@ -40,11 +40,11 @@
                                          public ConstrainedWindowMacDelegate {
  public:
   SSLClientAuthObserverCocoaBridge(
-      const content::BrowserContext* browser_context,
+      const net::HttpNetworkSession* network_session,
       net::SSLCertRequestInfo* cert_request_info,
       const chrome::SelectCertificateCallback& callback,
       SSLClientCertificateSelectorCocoa* controller)
-      : SSLClientAuthObserver(browser_context, cert_request_info, callback),
+      : SSLClientAuthObserver(network_session, cert_request_info, callback),
         controller_(controller) {
   }
 
@@ -71,13 +71,14 @@
 
 void ShowSSLClientCertificateSelector(
     content::WebContents* contents,
+    const net::HttpNetworkSession* network_session,
     net::SSLCertRequestInfo* cert_request_info,
     const SelectCertificateCallback& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // The dialog manages its own lifetime.
   SSLClientCertificateSelectorCocoa* selector =
       [[SSLClientCertificateSelectorCocoa alloc]
-          initWithBrowserContext:contents->GetBrowserContext()
+          initWithNetworkSession:network_session
                  certRequestInfo:cert_request_info
                         callback:callback];
   [selector displayForWebContents:contents];
@@ -87,14 +88,14 @@
 
 @implementation SSLClientCertificateSelectorCocoa
 
-- (id)initWithBrowserContext:(const content::BrowserContext*)browserContext
+- (id)initWithNetworkSession:(const net::HttpNetworkSession*)networkSession
     certRequestInfo:(net::SSLCertRequestInfo*)certRequestInfo
            callback:(const chrome::SelectCertificateCallback&)callback {
-  DCHECK(browserContext);
+  DCHECK(networkSession);
   DCHECK(certRequestInfo);
   if ((self = [super init])) {
     observer_.reset(new SSLClientAuthObserverCocoaBridge(
-        browserContext, certRequestInfo, callback, self));
+        networkSession, certRequestInfo, callback, self));
   }
   return self;
 }
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm
index a0c7110..37757d6 100644
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm
@@ -50,7 +50,7 @@
   int count = 0;
   SSLClientCertificateSelectorCocoa* selector =
       [[SSLClientCertificateSelectorCocoa alloc]
-          initWithBrowserContext:web_contents->GetBrowserContext()
+          initWithNetworkSession:auth_requestor_->http_network_session_
                  certRequestInfo:auth_requestor_->cert_request_info_.get()
                         callback:base::Bind(&OnCertificateSelected,
                                             &cert,
@@ -72,13 +72,13 @@
 
 // Test that switching to another tab correctly hides the sheet.
 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, HideShow) {
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
   SSLClientCertificateSelectorCocoa* selector =
       [[SSLClientCertificateSelectorCocoa alloc]
-          initWithBrowserContext:web_contents->GetBrowserContext()
+          initWithNetworkSession:auth_requestor_->http_network_session_
                  certRequestInfo:auth_requestor_->cert_request_info_.get()
                         callback:chrome::SelectCertificateCallback()];
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
   [selector displayForWebContents:web_contents];
   content::RunAllPendingInMessageLoop();
 
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 5ec6011..f9bf819 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -309,6 +309,10 @@
                                 browser_->host_desktop_type(), disposition);
     }
   }
+  UMA_HISTOGRAM_TIMES("WrenchMenu.TimeToAction.RecentTab",
+                       menu_opened_timer_.Elapsed());
+  UMA_HISTOGRAM_ENUMERATION("WrenchMenu.MenuAction", MENU_ACTION_RECENT_TAB,
+                             LIMIT_MENU_ACTION);
 }
 
 int RecentTabsSubMenuModel::GetFirstRecentTabsCommandId() {
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index b1eb408..34ba9fd 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -9,6 +9,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/task/cancelable_task_tracker.h"
+#include "base/timer/elapsed_timer.h"
 #include "chrome/browser/favicon/favicon_service.h"
 #include "chrome/browser/sessions/tab_restore_service.h"
 #include "chrome/browser/sessions/tab_restore_service_observer.h"
@@ -168,6 +169,9 @@
 
   base::WeakPtrFactory<RecentTabsSubMenuModel> weak_ptr_factory_;
 
+  // Time the menu is open for until a recent tab is selected.
+  base::ElapsedTimer menu_opened_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(RecentTabsSubMenuModel);
 };
 
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index cedb297..44a73e7 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -8,6 +8,7 @@
 #include <cmath>
 
 #include "base/command_line.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"
@@ -276,6 +277,7 @@
 WrenchMenuModel::WrenchMenuModel(ui::AcceleratorProvider* provider,
                                  Browser* browser)
     : ui::SimpleMenuModel(this),
+      uma_action_recorded_(false),
       provider_(provider),
       browser_(browser),
       tab_strip_model_(browser_->tab_strip_model()) {
@@ -404,17 +406,307 @@
     }
   }
 
-  if (command_id == IDC_HELP_PAGE_VIA_MENU)
-    content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
+  LogMenuMetrics(command_id);
+  chrome::ExecuteCommand(browser_, command_id);
+}
 
-  if (command_id == IDC_FULLSCREEN) {
-    // We issue the UMA command here and not in BrowserCommandController or even
-    // FullscreenController since we want to be able to distinguish this event
-    // and a menu which is under development.
-    content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
+void WrenchMenuModel::LogMenuMetrics(int command_id) {
+  base::TimeDelta delta = timer_.Elapsed();
+
+  switch (command_id) {
+    case IDC_NEW_TAB:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.NewTab", delta);
+      LogMenuAction(MENU_ACTION_NEW_TAB);
+      break;
+    case IDC_NEW_WINDOW:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.NewWindow", delta);
+      LogMenuAction(MENU_ACTION_NEW_WINDOW);
+      break;
+    case IDC_NEW_INCOGNITO_WINDOW:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.NewIncognitoWindow",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_NEW_INCOGNITO_WINDOW);
+      break;
+
+    // Bookmarks sub menu.
+    case IDC_SHOW_BOOKMARK_BAR:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowBookmarkBar",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_BAR);
+      break;
+    case IDC_SHOW_BOOKMARK_MANAGER:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowBookmarkMgr",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_SHOW_BOOKMARK_MANAGER);
+      break;
+    case IDC_IMPORT_SETTINGS:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ImportSettings",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_IMPORT_SETTINGS);
+      break;
+    case IDC_BOOKMARK_PAGE:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.BookmarkPage",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_BOOKMARK_PAGE);
+      break;
+    case IDC_BOOKMARK_ALL_TABS:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.BookmarkAllTabs",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_BOOKMARK_ALL_TABS);
+      break;
+    case IDC_PIN_TO_START_SCREEN:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.PinToStartScreen",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_PIN_TO_START_SCREEN);
+      break;
+
+    // Recent tabs menu.
+    case IDC_RESTORE_TAB:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.RestoreTab", delta);
+      LogMenuAction(MENU_ACTION_RESTORE_TAB);
+      break;
+
+    // Windows.
+    case IDC_WIN_DESKTOP_RESTART:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.WinDesktopRestart",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_WIN_DESKTOP_RESTART);
+      break;
+    case IDC_WIN8_METRO_RESTART:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Win8MetroRestart",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_WIN8_METRO_RESTART);
+      break;
+
+    case IDC_WIN_CHROMEOS_RESTART:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ChromeOSRestart",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_WIN_CHROMEOS_RESTART);
+      break;
+    case IDC_DISTILL_PAGE:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DistillPage",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_DISTILL_PAGE);
+      break;
+    case IDC_SAVE_PAGE:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.SavePage", delta);
+      LogMenuAction(MENU_ACTION_SAVE_PAGE);
+      break;
+    case IDC_FIND:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Find", delta);
+      LogMenuAction(MENU_ACTION_FIND);
+      break;
+    case IDC_PRINT:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Print", delta);
+      LogMenuAction(MENU_ACTION_PRINT);
+      break;
+
+    // Edit menu.
+    case IDC_CUT:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Cut", delta);
+      LogMenuAction(MENU_ACTION_CUT);
+      break;
+    case IDC_COPY:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Copy", delta);
+      LogMenuAction(MENU_ACTION_COPY);
+      break;
+    case IDC_PASTE:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Paste", delta);
+      LogMenuAction(MENU_ACTION_PASTE);
+      break;
+
+    // Tools menu.
+    case IDC_CREATE_HOSTED_APP:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.CreateHostedApp",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_CREATE_HOSTED_APP);
+      break;
+    case IDC_CREATE_SHORTCUTS:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.CreateShortcuts",
+                                   delta);
+      LogMenuAction(MENU_ACTION_CREATE_SHORTCUTS);
+      break;
+    case IDC_MANAGE_EXTENSIONS:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ManageExtensions",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_MANAGE_EXTENSIONS);
+      break;
+    case IDC_TASK_MANAGER:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.TaskManager",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_TASK_MANAGER);
+      break;
+    case IDC_CLEAR_BROWSING_DATA:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ClearBrowsingData",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_CLEAR_BROWSING_DATA);
+      break;
+    case IDC_VIEW_SOURCE:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ViewSource", delta);
+      LogMenuAction(MENU_ACTION_VIEW_SOURCE);
+      break;
+    case IDC_DEV_TOOLS:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DevTools", delta);
+      LogMenuAction(MENU_ACTION_DEV_TOOLS);
+      break;
+    case IDC_DEV_TOOLS_CONSOLE:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DevToolsConsole",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_DEV_TOOLS_CONSOLE);
+      break;
+    case IDC_DEV_TOOLS_DEVICES:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.DevToolsDevices",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_DEV_TOOLS_DEVICES);
+      break;
+    case IDC_PROFILING_ENABLED:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ProfilingEnabled",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_PROFILING_ENABLED);
+      break;
+
+    // Zoom menu
+    case IDC_ZOOM_MINUS:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ZoomMinus", delta);
+        LogMenuAction(MENU_ACTION_ZOOM_MINUS);
+      }
+      break;
+    case IDC_ZOOM_PLUS:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ZoomPlus", delta);
+        LogMenuAction(MENU_ACTION_ZOOM_PLUS);
+      }
+      break;
+    case IDC_FULLSCREEN:
+      content::RecordAction(UserMetricsAction("EnterFullScreenWithWrenchMenu"));
+
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.EnterFullScreen",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_FULLSCREEN);
+      break;
+
+    case IDC_SHOW_HISTORY:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowHistory",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_SHOW_HISTORY);
+      break;
+    case IDC_SHOW_DOWNLOADS:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowDownloads",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_SHOW_DOWNLOADS);
+      break;
+    case IDC_SHOW_SYNC_SETUP:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.ShowSyncSetup",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_SHOW_SYNC_SETUP);
+      break;
+    case IDC_OPTIONS:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Settings", delta);
+      LogMenuAction(MENU_ACTION_OPTIONS);
+      break;
+    case IDC_ABOUT:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.About", delta);
+      LogMenuAction(MENU_ACTION_ABOUT);
+      break;
+
+    // Help menu.
+    case IDC_HELP_PAGE_VIA_MENU:
+      content::RecordAction(UserMetricsAction("ShowHelpTabViaWrenchMenu"));
+
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.HelpPage", delta);
+      LogMenuAction(MENU_ACTION_HELP_PAGE_VIA_MENU);
+      break;
+  #if defined(GOOGLE_CHROME_BUILD)
+    case IDC_FEEDBACK:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Feedback", delta);
+      LogMenuAction(MENU_ACTION_FEEDBACK);
+      break;
+  #endif
+
+    case IDC_TOGGLE_REQUEST_TABLET_SITE:
+      if (!uma_action_recorded_) {
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.RequestTabletSite",
+                                   delta);
+      }
+      LogMenuAction(MENU_ACTION_TOGGLE_REQUEST_TABLET_SITE);
+      break;
+    case IDC_EXIT:
+      if (!uma_action_recorded_)
+        UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction.Exit", delta);
+      LogMenuAction(MENU_ACTION_EXIT);
+      break;
   }
 
-  chrome::ExecuteCommand(browser_, command_id);
+  if (!uma_action_recorded_) {
+    UMA_HISTOGRAM_MEDIUM_TIMES("WrenchMenu.TimeToAction", delta);
+    uma_action_recorded_ = true;
+  }
+}
+
+void WrenchMenuModel::LogMenuAction(int action_id) {
+  UMA_HISTOGRAM_ENUMERATION("WrenchMenu.MenuAction", action_id,
+                            LIMIT_MENU_ACTION);
 }
 
 bool WrenchMenuModel::IsCommandIdChecked(int command_id) const {
@@ -665,6 +957,7 @@
   }
 
   RemoveTrailingSeparators();
+  uma_action_recorded_ = false;
 }
 
 void WrenchMenuModel::AddGlobalErrorMenuItems() {
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.h b/chrome/browser/ui/toolbar/wrench_menu_model.h
index ff787c8..4b9cefe 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.h
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.h
@@ -7,6 +7,8 @@
 
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/notification_observer.h"
@@ -24,6 +26,54 @@
 class MockWrenchMenuModel;
 }  // namespace
 
+enum WrenchMenuAction {
+  MENU_ACTION_NEW_TAB = 0,
+  MENU_ACTION_NEW_WINDOW,
+  MENU_ACTION_NEW_INCOGNITO_WINDOW,
+  MENU_ACTION_SHOW_BOOKMARK_BAR,
+  MENU_ACTION_SHOW_BOOKMARK_MANAGER,
+  MENU_ACTION_IMPORT_SETTINGS,
+  MENU_ACTION_BOOKMARK_PAGE,
+  MENU_ACTION_BOOKMARK_ALL_TABS,
+  MENU_ACTION_PIN_TO_START_SCREEN,
+  MENU_ACTION_RESTORE_TAB,
+  MENU_ACTION_WIN_DESKTOP_RESTART,
+  MENU_ACTION_WIN8_METRO_RESTART,
+  MENU_ACTION_WIN_CHROMEOS_RESTART,
+  MENU_ACTION_DISTILL_PAGE,
+  MENU_ACTION_SAVE_PAGE,
+  MENU_ACTION_FIND,
+  MENU_ACTION_PRINT,
+  MENU_ACTION_CUT,
+  MENU_ACTION_COPY,
+  MENU_ACTION_PASTE,
+  MENU_ACTION_CREATE_HOSTED_APP,
+  MENU_ACTION_CREATE_SHORTCUTS,
+  MENU_ACTION_MANAGE_EXTENSIONS,
+  MENU_ACTION_TASK_MANAGER,
+  MENU_ACTION_CLEAR_BROWSING_DATA,
+  MENU_ACTION_VIEW_SOURCE,
+  MENU_ACTION_DEV_TOOLS,
+  MENU_ACTION_DEV_TOOLS_CONSOLE,
+  MENU_ACTION_DEV_TOOLS_DEVICES,
+  MENU_ACTION_PROFILING_ENABLED,
+  MENU_ACTION_ZOOM_MINUS,
+  MENU_ACTION_ZOOM_PLUS,
+  MENU_ACTION_FULLSCREEN,
+  MENU_ACTION_SHOW_HISTORY,
+  MENU_ACTION_SHOW_DOWNLOADS,
+  MENU_ACTION_SHOW_SYNC_SETUP,
+  MENU_ACTION_OPTIONS,
+  MENU_ACTION_ABOUT,
+  MENU_ACTION_HELP_PAGE_VIA_MENU,
+  MENU_ACTION_FEEDBACK,
+  MENU_ACTION_TOGGLE_REQUEST_TABLET_SITE,
+  MENU_ACTION_EXIT,
+  MENU_ACTION_RECENT_TAB,
+  MENU_ACTION_BOOKMARK_OPEN,
+  LIMIT_MENU_ACTION
+};
+
 // A menu model that builds the contents of an encoding menu.
 class EncodingMenuModel : public ui::SimpleMenuModel,
                           public ui::SimpleMenuModel::Delegate {
@@ -157,6 +207,23 @@
 
   bool ShouldShowNewIncognitoWindowMenuItem();
 
+  // Called when a command is selected.
+  // Logs UMA metrics about which command was chosen and how long the user
+  // took to select the command.
+  void LogMenuMetrics(int command_id);
+
+  // Helper function to record the menu action in a UMA histogram.
+  void LogMenuAction(int action_id);
+
+  // Time menu has been open. Used by LogMenuMetrics() to record the time
+  // to action when the user selects a menu item.
+  base::ElapsedTimer timer_;
+
+  // Whether a UMA menu action has been recorded since the menu is open.
+  // Only the first time to action is recorded since some commands
+  // (zoom controls) don't dimiss the menu.
+  bool uma_action_recorded_;
+
   // Models for the special menu items with buttons.
   scoped_ptr<ui::ButtonMenuItemModel> edit_menu_item_model_;
   scoped_ptr<ui::ButtonMenuItemModel> zoom_menu_item_model_;
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector.cc b/chrome/browser/ui/views/ssl_client_certificate_selector.cc
index 969de17..0a03027 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector.cc
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector.cc
@@ -82,10 +82,10 @@
 
 SSLClientCertificateSelector::SSLClientCertificateSelector(
     content::WebContents* web_contents,
+    const net::HttpNetworkSession* network_session,
     const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
     const chrome::SelectCertificateCallback& callback)
-    : SSLClientAuthObserver(web_contents->GetBrowserContext(),
-                            cert_request_info, callback),
+    : SSLClientAuthObserver(network_session, cert_request_info, callback),
       model_(new CertificateSelectorTableModel(cert_request_info.get())),
       web_contents_(web_contents),
       table_(NULL),
@@ -274,12 +274,13 @@
 
 void ShowSSLClientCertificateSelector(
     content::WebContents* contents,
+    const net::HttpNetworkSession* network_session,
     net::SSLCertRequestInfo* cert_request_info,
     const chrome::SelectCertificateCallback& callback) {
   DVLOG(1) << __FUNCTION__ << " " << contents;
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   (new SSLClientCertificateSelector(
-       contents, cert_request_info, callback))->Init();
+       contents, network_session, cert_request_info, callback))->Init();
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector.h b/chrome/browser/ui/views/ssl_client_certificate_selector.h
index de4fbed..882b4b0 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector.h
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector.h
@@ -40,6 +40,7 @@
  public:
   SSLClientCertificateSelector(
       content::WebContents* web_contents,
+      const net::HttpNetworkSession* network_session,
       const scoped_refptr<net::SSLCertRequestInfo>& cert_request_info,
       const chrome::SelectCertificateCallback& callback);
   ~SSLClientCertificateSelector() override;
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc b/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
index 390abd4..b5dba23 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
@@ -73,6 +73,7 @@
         browser()->tab_strip_model()->GetActiveWebContents());
     selector_ = new SSLClientCertificateSelector(
         browser()->tab_strip_model()->GetActiveWebContents(),
+        auth_requestor_->http_network_session_,
         auth_requestor_->cert_request_info_,
         base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
                    auth_requestor_));
@@ -160,12 +161,14 @@
 
     selector_1_ = new SSLClientCertificateSelector(
         browser()->tab_strip_model()->GetWebContentsAt(1),
+        auth_requestor_1_->http_network_session_,
         auth_requestor_1_->cert_request_info_,
         base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
                    auth_requestor_1_));
     selector_1_->Init();
     selector_2_ = new SSLClientCertificateSelector(
         browser()->tab_strip_model()->GetWebContentsAt(2),
+        auth_requestor_2_->http_network_session_,
         auth_requestor_2_->cert_request_info_,
         base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
                    auth_requestor_2_));
@@ -236,6 +239,7 @@
 
     selector_1_ = new SSLClientCertificateSelector(
         browser_1_->tab_strip_model()->GetActiveWebContents(),
+        auth_requestor_1_->http_network_session_,
         auth_requestor_1_->cert_request_info_,
         base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
                    auth_requestor_1_));
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
index b882cc5..50dc01f 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
@@ -153,9 +153,6 @@
     const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
     const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
 #if defined(USE_AURA)
-  if (!browser_defaults::kShowLinkDisambiguationPopup)
-    return;
-
   link_disambiguation_popup_.reset(new LinkDisambiguationPopup);
   link_disambiguation_popup_->Show(
       views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView()),
diff --git a/chrome/browser/ui/views/toolbar/wrench_menu.cc b/chrome/browser/ui/views/toolbar/wrench_menu.cc
index 8c1d8d2..f057fb5 100644
--- a/chrome/browser/ui/views/toolbar/wrench_menu.cc
+++ b/chrome/browser/ui/views/toolbar/wrench_menu.cc
@@ -8,6 +8,7 @@
 #include <cmath>
 #include <set>
 
+#include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -1001,6 +1002,10 @@
 
 void WrenchMenu::ExecuteCommand(int command_id, int mouse_event_flags) {
   if (IsBookmarkCommand(command_id)) {
+    UMA_HISTOGRAM_TIMES("WrenchMenu.TimeToAction.BookmarkOpen",
+                        menu_opened_timer_.Elapsed());
+    UMA_HISTOGRAM_ENUMERATION("WrenchMenu.MenuAction",
+                              MENU_ACTION_BOOKMARK_OPEN, LIMIT_MENU_ACTION);
     bookmark_menu_delegate_->ExecuteCommand(command_id, mouse_event_flags);
     return;
   }
diff --git a/chrome/browser/ui/views/toolbar/wrench_menu.h b/chrome/browser/ui/views/toolbar/wrench_menu.h
index 267f1de..6dfbe1a 100644
--- a/chrome/browser/ui/views/toolbar/wrench_menu.h
+++ b/chrome/browser/ui/views/toolbar/wrench_menu.h
@@ -10,6 +10,8 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
+#include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
 #include "components/bookmarks/browser/base_bookmark_model_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -184,6 +186,9 @@
 
   ObserverList<WrenchMenuObserver> observer_list_;
 
+  // Records the time from when menu opens to when the user selects a menu item.
+  base::ElapsedTimer menu_opened_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(WrenchMenu);
 };
 
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 9e3ac1c..368fb5e 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -13,6 +13,8 @@
 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
 #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h"
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h"
+#include "chrome/browser/chromeos/login/screens/error_screen.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/policy/consumer_management_service.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
@@ -273,6 +275,15 @@
   error_screen_handler_ = new ErrorScreenHandler(network_state_informer_);
   AddScreenHandler(error_screen_handler_);
 
+  // Initialize ErrorScreen if it hasn't initialized.
+  if (WizardController::default_controller()) {
+    BaseScreen* screen = WizardController::default_controller()->GetScreen(
+        WizardController::kErrorScreenName);
+    CHECK(screen);
+  } else {
+    error_screen_.reset(new ErrorScreen(nullptr, error_screen_handler_));
+  }
+
   EnrollmentScreenHandler* enrollment_screen_handler =
       new EnrollmentScreenHandler(network_state_informer_,
                                   error_screen_handler_);
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index ee73c32..1e34272 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -11,6 +11,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "chrome/browser/chromeos/login/ui/oobe_display.h"
 #include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h"
@@ -25,7 +26,9 @@
 class BaseScreenHandler;
 class ControllerPairingScreenActor;
 class DeviceDisabledScreenActor;
+class ErrorScreen;
 class ErrorScreenHandler;
+class GaiaScreenHandler;
 class HostPairingScreenActor;
 class KioskAppMenuHandler;
 class KioskEnableScreenActor;
@@ -33,7 +36,6 @@
 class NativeWindowDelegate;
 class NetworkDropdownHandler;
 class NetworkStateInformer;
-class GaiaScreenHandler;
 class SigninScreenHandler;
 class SigninScreenHandlerDelegate;
 class UpdateScreenHandler;
@@ -221,6 +223,8 @@
 
   KioskAppMenuHandler* kiosk_app_menu_handler_;  // Non-owning pointers.
 
+  scoped_ptr<ErrorScreen> error_screen_;
+
   // Id of the current oobe/login screen.
   Screen current_screen_;
 
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index 8883413..2bcd470 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -64,45 +64,49 @@
   return true;
 }
 
-// Updates a registry key |name| to be |value| for the given |app_reg_data|.
-// If this is a |system_install|, then update the value under HKLM (istead of
-// HKCU for user-installs) using a group of keys (one for each OS user) and also
-// include the method to |aggregate| these values when reporting.
-bool WriteGoogleUpdateStrKeyInternal(const AppRegistrationData& app_reg_data,
-                                     bool system_install,
-                                     const wchar_t* const name,
-                                     const base::string16& value,
-                                     const wchar_t* const aggregate) {
+// Writes |value| into a user-specific value in the key |name| under
+// |app_reg_data|'s ClientStateMedium key in HKLM along with the aggregation
+// method |aggregate|. This function is solely for use by system-level installs.
+bool WriteGoogleUpdateAggregateNumKeyInternal(
+    const AppRegistrationData& app_reg_data,
+    const wchar_t* const name,
+    int value,
+    const wchar_t* const aggregate) {
+  DCHECK(aggregate);
+  DCHECK(GoogleUpdateSettings::IsSystemInstall());
   const REGSAM kAccess = KEY_SET_VALUE | KEY_WOW64_32KEY;
-  if (system_install) {
-    DCHECK(aggregate);
-    // Machine installs require each OS user to write a unique key under a
-    // named key in HKLM as well as an "aggregation" function that describes
-    // how the values of multiple users are to be combined.
-    base::string16 uniquename;
-    if (!base::win::GetUserSidString(&uniquename)) {
-      NOTREACHED();
-      return false;
-    }
 
-    base::string16 reg_path(app_reg_data.GetStateMediumKey());
-    reg_path.append(L"\\");
-    reg_path.append(name);
-    RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), kAccess);
-    key.WriteValue(google_update::kRegAggregateMethod, aggregate);
-    return (key.WriteValue(uniquename.c_str(), value.c_str()) == ERROR_SUCCESS);
-  } else {
-    // User installs are easy: just write the values to HKCU tree.
-    RegKey key(HKEY_CURRENT_USER, app_reg_data.GetStateKey().c_str(), kAccess);
-    return (key.WriteValue(name, value.c_str()) == ERROR_SUCCESS);
+  // Machine installs require each OS user to write a unique key under a
+  // named key in HKLM as well as an "aggregation" function that describes
+  // how the values of multiple users are to be combined.
+  base::string16 uniquename;
+  if (!base::win::GetUserSidString(&uniquename)) {
+    NOTREACHED();
+    return false;
   }
+
+  base::string16 reg_path(app_reg_data.GetStateMediumKey());
+  reg_path.append(L"\\");
+  reg_path.append(name);
+  RegKey key(HKEY_LOCAL_MACHINE, reg_path.c_str(), kAccess);
+  key.WriteValue(google_update::kRegAggregateMethod, aggregate);
+  return (key.WriteValue(uniquename.c_str(), value) == ERROR_SUCCESS);
+}
+
+// Updates a registry key |name| to be |value| for the given |app_reg_data|.
+bool WriteGoogleUpdateStrKeyInternal(const AppRegistrationData& app_reg_data,
+                                     const wchar_t* const name,
+                                     const base::string16& value) {
+  const REGSAM kAccess = KEY_SET_VALUE | KEY_WOW64_32KEY;
+  RegKey key(HKEY_CURRENT_USER, app_reg_data.GetStateKey().c_str(), kAccess);
+  return (key.WriteValue(name, value.c_str()) == ERROR_SUCCESS);
 }
 
 bool WriteGoogleUpdateStrKey(const wchar_t* const name,
                              const base::string16& value) {
   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
   return WriteGoogleUpdateStrKeyInternal(
-      dist->GetAppRegistrationData(), false, name, value, NULL);
+      dist->GetAppRegistrationData(), name, value);
 }
 
 bool ClearGoogleUpdateStrKey(const wchar_t* const name) {
@@ -434,10 +438,8 @@
     const AppRegistrationData& app_reg_data,
     bool did_run) {
   return WriteGoogleUpdateStrKeyInternal(app_reg_data,
-                                         false, // user level.
                                          google_update::kRegDidRunField,
-                                         did_run ? L"1" : L"0",
-                                         NULL);
+                                         did_run ? L"1" : L"0");
 }
 
 bool GoogleUpdateSettings::UpdateDidRunState(bool did_run, bool system_level) {
@@ -547,17 +549,31 @@
 void GoogleUpdateSettings::UpdateProfileCounts(int profiles_active,
                                                int profiles_signedin) {
   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
-  bool system_install = IsSystemInstall();
-  WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
-                                  system_install,
-                                  google_update::kRegProfilesActive,
-                                  base::Int64ToString16(profiles_active),
-                                  L"sum()");
-  WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
-                                  system_install,
-                                  google_update::kRegProfilesSignedIn,
-                                  base::Int64ToString16(profiles_signedin),
-                                  L"sum()");
+  // System-level installs must write into the ClientStateMedium key shared by
+  // all users. Special treatment is used to aggregate across those users.
+  if (IsSystemInstall()) {
+    // Write the counts as ints that get aggregated across all users via
+    // summation for system-level installs.
+    WriteGoogleUpdateAggregateNumKeyInternal(
+        dist->GetAppRegistrationData(),
+        google_update::kRegProfilesActive,
+        profiles_active,
+        L"sum()");
+    WriteGoogleUpdateAggregateNumKeyInternal(
+        dist->GetAppRegistrationData(),
+        google_update::kRegProfilesSignedIn,
+        profiles_signedin,
+        L"sum()");
+  } else {
+    // Write the counts as strings since no aggregation function is needed for
+    // user-level installs.
+    WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
+                                    google_update::kRegProfilesActive,
+                                    base::IntToString16(profiles_active));
+    WriteGoogleUpdateStrKeyInternal(dist->GetAppRegistrationData(),
+                                    google_update::kRegProfilesSignedIn,
+                                    base::IntToString16(profiles_signedin));
+  }
 }
 
 int GoogleUpdateSettings::DuplicateGoogleUpdateSystemClientKey() {
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index ecab320..3e7943f 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -8,10 +8,14 @@
 #include <shlwapi.h>  // For SHDeleteKey.
 
 #include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_path_override.h"
 #include "base/test/test_reg_util_win.h"
 #include "base/win/registry.h"
+#include "base/win/win_util.h"
 #include "chrome/common/chrome_constants.h"
+#include "chrome/installer/util/app_registration_data.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/channel_info.h"
 #include "chrome/installer/util/fake_installation_state.h"
@@ -35,6 +39,11 @@
 class GoogleUpdateSettingsTest : public testing::Test {
  protected:
   virtual void SetUp() override {
+    base::FilePath program_files_path;
+    PathService::Get(base::DIR_PROGRAM_FILES, &program_files_path);
+    program_files_override_.reset(new base::ScopedPathOverride(
+        base::DIR_PROGRAM_FILES, program_files_path));
+
     registry_overrides_.OverrideRegistry(HKEY_LOCAL_MACHINE);
     registry_overrides_.OverrideRegistry(HKEY_CURRENT_USER);
   }
@@ -297,6 +306,8 @@
                time_in_minutes) == ERROR_SUCCESS;
   }
 
+  // Keep Program Files path so InstallUtil::IsPerUserInstall doesn't crash.
+  scoped_ptr<base::ScopedPathOverride> program_files_override_;
   registry_util::RegistryOverrideManager registry_overrides_;
 };
 
@@ -628,6 +639,113 @@
   EXPECT_FALSE(is_overridden);
 }
 
+TEST_F(GoogleUpdateSettingsTest, UpdateProfileCountsSystemInstall) {
+  // Pretend to be a system install for GoogleUpdateSettings::IsSystemInstall().
+  base::FilePath program_files_path;
+  PathService::Get(base::DIR_PROGRAM_FILES, &program_files_path);
+  base::ScopedPathOverride dir_module_override(base::DIR_MODULE,
+                                               program_files_path);
+
+  // No profile count keys present yet.
+  const base::string16& state_key = BrowserDistribution::GetDistribution()->
+      GetAppRegistrationData().GetStateMediumKey();
+  base::string16 num_profiles_path(state_key);
+  num_profiles_path.append(L"\\");
+  num_profiles_path.append(google_update::kRegProfilesActive);
+  base::string16 num_signed_in_path(state_key);
+  num_signed_in_path.append(L"\\");
+  num_signed_in_path.append(google_update::kRegProfilesSignedIn);
+
+  EXPECT_EQ(ERROR_FILE_NOT_FOUND,
+            RegKey().Open(HKEY_LOCAL_MACHINE,
+                          num_profiles_path.c_str(),
+                          KEY_QUERY_VALUE));
+  EXPECT_EQ(ERROR_FILE_NOT_FOUND,
+            RegKey().Open(HKEY_LOCAL_MACHINE,
+                          num_signed_in_path.c_str(),
+                          KEY_QUERY_VALUE));
+
+  // Show time! Write the values.
+  GoogleUpdateSettings::UpdateProfileCounts(3, 2);
+
+  // Verify the keys were created.
+  EXPECT_EQ(ERROR_SUCCESS,
+            RegKey().Open(HKEY_LOCAL_MACHINE,
+                          num_profiles_path.c_str(),
+                          KEY_QUERY_VALUE));
+  EXPECT_EQ(ERROR_SUCCESS,
+            RegKey().Open(HKEY_LOCAL_MACHINE,
+                          num_signed_in_path.c_str(),
+                          KEY_QUERY_VALUE));
+
+  base::string16 uniquename;
+  EXPECT_TRUE(base::win::GetUserSidString(&uniquename));
+
+  // Verify the values are accessible.
+  DWORD num_profiles = 0;
+  DWORD num_signed_in = 0;
+  base::string16 aggregate;
+  EXPECT_EQ(
+      ERROR_SUCCESS,
+      RegKey(HKEY_LOCAL_MACHINE, num_profiles_path.c_str(),
+             KEY_QUERY_VALUE).ReadValueDW(uniquename.c_str(),
+                                          &num_profiles));
+  EXPECT_EQ(
+      ERROR_SUCCESS,
+      RegKey(HKEY_LOCAL_MACHINE, num_signed_in_path.c_str(),
+             KEY_QUERY_VALUE).ReadValueDW(uniquename.c_str(),
+                                          &num_signed_in));
+  EXPECT_EQ(
+      ERROR_SUCCESS,
+      RegKey(HKEY_LOCAL_MACHINE, num_signed_in_path.c_str(),
+             KEY_QUERY_VALUE).ReadValue(google_update::kRegAggregateMethod,
+                                        &aggregate));
+
+  // Verify the correct values were written.
+  EXPECT_EQ(3, num_profiles);
+  EXPECT_EQ(2, num_signed_in);
+  EXPECT_EQ(L"sum()", aggregate);
+}
+
+TEST_F(GoogleUpdateSettingsTest, UpdateProfileCountsUserInstall) {
+  // Unit tests never operate as an installed application, so will never
+  // be a system install.
+
+  // No profile count values present yet.
+  const base::string16& state_key = BrowserDistribution::GetDistribution()->
+      GetAppRegistrationData().GetStateKey();
+
+  EXPECT_EQ(ERROR_FILE_NOT_FOUND,
+            RegKey().Open(HKEY_CURRENT_USER,
+                          state_key.c_str(),
+                          KEY_QUERY_VALUE));
+
+  // Show time! Write the values.
+  GoogleUpdateSettings::UpdateProfileCounts(4, 1);
+
+  // Verify the key was created.
+  EXPECT_EQ(ERROR_SUCCESS,
+            RegKey().Open(HKEY_CURRENT_USER,
+                          state_key.c_str(),
+                          KEY_QUERY_VALUE));
+
+  // Verify the values are accessible.
+  base::string16 num_profiles;
+  base::string16 num_signed_in;
+  EXPECT_EQ(
+      ERROR_SUCCESS,
+      RegKey(HKEY_CURRENT_USER, state_key.c_str(), KEY_QUERY_VALUE).
+          ReadValue(google_update::kRegProfilesActive, &num_profiles));
+  EXPECT_EQ(
+      ERROR_SUCCESS,
+      RegKey(HKEY_CURRENT_USER, state_key.c_str(), KEY_QUERY_VALUE).
+          ReadValue(google_update::kRegProfilesSignedIn, &num_signed_in));
+
+  // Verify the correct values were written.
+  EXPECT_EQ(L"4", num_profiles);
+  EXPECT_EQ(L"1", num_signed_in);
+}
+
 #if defined(GOOGLE_CHROME_BUILD)
 
 // Test that the default override is returned if no app-specific override is
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index c6b3a5a..dd95406 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -37,9 +37,6 @@
 // Disables the ChromeOS demo.
 const char kDisableDemoMode[] = "disable-demo-mode";
 
-// Disable Easy sign-in.
-const char kDisableEasySignin[] = "disable-easy-signin";
-
 // Disable HID-detection OOBE screen.
 const char kDisableHIDDetectionOnOOBE[] = "disable-hid-detection-on-oobe";
 
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 049c1dc..bec2bca 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -31,7 +31,6 @@
 CHROMEOS_EXPORT extern const char kDisableBootAnimation[];
 CHROMEOS_EXPORT extern const char kDisableDemoMode[];
 CHROMEOS_EXPORT extern const char kDisableDeviceDisabling[];
-CHROMEOS_EXPORT extern const char kDisableEasySignin[];
 CHROMEOS_EXPORT extern const char kDisableGaiaServices[];
 CHROMEOS_EXPORT extern const char kDisableHIDDetectionOnOOBE[];
 CHROMEOS_EXPORT extern const char kDisableLoginAnimations[];
diff --git a/components/autofill/core/common/password_form.cc b/components/autofill/core/common/password_form.cc
index 0f3ee64..69c3200 100644
--- a/components/autofill/core/common/password_form.cc
+++ b/components/autofill/core/common/password_form.cc
@@ -5,6 +5,7 @@
 #include <ostream>
 
 #include "base/strings/string16.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/autofill/core/common/password_form.h"
 
@@ -73,6 +74,8 @@
             << base::UTF16ToUTF8(form.new_password_element)
             << " new_password_value: "
             << base::UTF16ToUTF8(form.new_password_value)
+            << " other_possible_usernames: "
+            << JoinString(form.other_possible_usernames, '|')
             << " autocomplete_set:" << form.password_autocomplete_set
             << " blacklisted: " << form.blacklisted_by_user
             << " preferred: " << form.preferred
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.cc
index 125d8ac..6ce7f7b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.cc
@@ -40,7 +40,7 @@
     return nullptr;
   DataReductionProxyBypassType bypass_type = BYPASS_EVENT_TYPE_MAX;
   bool should_retry = data_reduction_proxy::MaybeBypassProxyAndPrepareToRetry(
-      params_, request, request->response_info().headers.get(), &bypass_type);
+      params_, request, &bypass_type);
   if (usage_stats_ && bypass_type != BYPASS_EVENT_TYPE_MAX)
     usage_stats_->SetBypassType(bypass_type);
   if (!should_retry)
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.cc
index 17b3f80..876cb2e 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.cc
@@ -43,10 +43,14 @@
 bool MaybeBypassProxyAndPrepareToRetry(
     const DataReductionProxyParams* data_reduction_proxy_params,
     net::URLRequest* request,
-    const net::HttpResponseHeaders* original_response_headers,
     DataReductionProxyBypassType* proxy_bypass_type) {
+  DCHECK(request);
   if (!data_reduction_proxy_params)
     return false;
+  const net::HttpResponseHeaders* response_headers =
+      request->response_info().headers.get();
+  if (!response_headers)
+    return false;
   DataReductionProxyTypeInfo data_reduction_proxy_type_info;
   if (!data_reduction_proxy_params->WasDataReductionProxyUsed(
           request, &data_reduction_proxy_type_info)) {
@@ -68,15 +72,15 @@
   // via header, so detect and report cases where the via header is missing.
   DataReductionProxyUsageStats::DetectAndRecordMissingViaHeaderResponseCode(
       !data_reduction_proxy_type_info.proxy_servers.second.is_empty(),
-      original_response_headers);
+      response_headers);
 
   DataReductionProxyTamperDetection::DetectAndReport(
-      original_response_headers,
+      response_headers,
       data_reduction_proxy_type_info.proxy_servers.first.SchemeIsSecure());
 
   DataReductionProxyInfo data_reduction_proxy_info;
   DataReductionProxyBypassType bypass_type =
-      GetDataReductionProxyBypassType(original_response_headers,
+      GetDataReductionProxyBypassType(response_headers,
                                       &data_reduction_proxy_info);
 
   if (bypass_type == BYPASS_EVENT_TYPE_MISSING_VIA_HEADER_OTHER &&
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.h
index 13aae29..faf7729 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol.h
@@ -34,7 +34,6 @@
 bool MaybeBypassProxyAndPrepareToRetry(
     const DataReductionProxyParams* params,
     net::URLRequest* request,
-    const net::HttpResponseHeaders* original_response_headers,
     DataReductionProxyBypassType* proxy_bypass_type);
 
 // Adds data reduction proxies to |result|, where applicable, if result
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol_unittest.cc
index 3625d60..c61b4f7 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_protocol_unittest.cc
@@ -123,19 +123,10 @@
   // if |expect_response_body|.
   void TestProxyFallback(const char* method,
                          const char* first_response,
-                         bool has_origin,
                          bool expected_retry,
+                         bool generate_response_error,
                          size_t expected_bad_proxy_count,
                          bool expect_response_body) {
-    std::string payload1 =
-        (expected_retry ? "Bypass message" : "content");
-    MockRead data_reads[] = {
-      MockRead(first_response),
-      MockRead(payload1.c_str()),
-      MockRead(net::SYNCHRONOUS, net::OK),
-    };
-    std::string origin = has_origin ? "Origin: foo.com\r\n" : "";
-
     std::string m(method);
     std::string trailer =
         (m == "HEAD" || m == "PUT" || m == "POST") ?
@@ -144,56 +135,78 @@
     std::string request1 =
         base::StringPrintf("%s http://www.google.com/ HTTP/1.1\r\n"
                            "Host: www.google.com\r\n"
-                           "Proxy-Connection: keep-alive\r\n%s%s"
+                           "Proxy-Connection: keep-alive\r\n%s"
                            "User-Agent:\r\n"
                            "Accept-Encoding: gzip, deflate\r\n\r\n",
-                           method, origin.c_str(), trailer.c_str());
+                           method, trailer.c_str());
+
+    std::string payload1 =
+        (expected_retry ? "Bypass message" : "content");
+
     MockWrite data_writes[] = {
       MockWrite(request1.c_str()),
     };
+
+    MockRead data_reads[] = {
+      MockRead(first_response),
+      MockRead(payload1.c_str()),
+      MockRead(net::SYNCHRONOUS, net::OK),
+    };
+    MockRead data_reads_error[] = {
+      MockRead(net::SYNCHRONOUS, net::ERR_INVALID_RESPONSE),
+    };
+
     StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
                                   data_writes, arraysize(data_writes));
-    mock_socket_factory_.AddSocketDataProvider(&data1);
+    StaticSocketDataProvider data1_error(data_reads_error,
+                                         arraysize(data_reads_error),
+                                         data_writes, arraysize(data_writes));
+    if (!generate_response_error)
+      mock_socket_factory_.AddSocketDataProvider(&data1);
+    else
+      mock_socket_factory_.AddSocketDataProvider(&data1_error);
 
-      std::string response2;
-      std::string request2;
-      if (expected_bad_proxy_count >= 2u ||
-          (m != "POST" && expected_retry && expected_bad_proxy_count == 0u)) {
-        response2 =
-            "HTTP/1.0 200 OK\r\n"
-            "Server: not-proxy\r\n\r\n";
-        request2 = base::StringPrintf(
-            "%s / HTTP/1.1\r\n"
-            "Host: www.google.com\r\n"
-            "Connection: keep-alive\r\n%s%s"
-            "User-Agent:\r\n"
-            "Accept-Encoding: gzip, deflate\r\n\r\n",
-            method, origin.c_str(), trailer.c_str());
-      } else if (expected_bad_proxy_count <= 1u) {
-        response2 =
-            "HTTP/1.0 200 OK\r\n"
-            "Server: not-proxy\r\n"
-            "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n";
-        request2 = base::StringPrintf(
-            "%s http://www.google.com/ HTTP/1.1\r\n"
-            "Host: www.google.com\r\n"
-            "Proxy-Connection: keep-alive\r\n%s%s"
-            "User-Agent:\r\n"
-            "Accept-Encoding: gzip, deflate\r\n\r\n",
-            method, origin.c_str(), trailer.c_str());
-      }
-      MockRead data_reads2[] = {
-          MockRead(response2.c_str()),
-          MockRead("content"),
-          MockRead(net::SYNCHRONOUS, net::OK),
-      };
-      MockWrite data_writes2[] = {
-          MockWrite(request2.c_str()),
-      };
-      StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
-                                     data_writes2, arraysize(data_writes2));
-      if (expected_retry) {
-        mock_socket_factory_.AddSocketDataProvider(&data2);
+    std::string response2;
+    std::string request2;
+    std::string response2_via_header = "";
+    std::string request2_connection_type = "";
+    std::string request2_path = "/";
+    bool idempotent_block_once =
+        m != "POST" && expected_retry && expected_bad_proxy_count == 0u;
+
+    if (expected_bad_proxy_count < 2u && !idempotent_block_once) {
+      request2_path = "http://www.google.com/";
+      request2_connection_type = "Proxy-";
+      response2_via_header = "Via: 1.1 Chrome-Compression-Proxy\r\n";
+    }
+
+    request2 = base::StringPrintf(
+        "%s %s HTTP/1.1\r\n"
+        "Host: www.google.com\r\n"
+        "%sConnection: keep-alive\r\n%s"
+        "User-Agent:\r\n"
+        "Accept-Encoding: gzip, deflate\r\n\r\n",
+        method, request2_path.c_str(), request2_connection_type.c_str(),
+        trailer.c_str());
+
+    response2 = base::StringPrintf(
+        "HTTP/1.0 200 OK\r\n"
+        "Server: foo\r\n%s\r\n", response2_via_header.c_str());
+
+    MockWrite data_writes2[] = {
+      MockWrite(request2.c_str()),
+    };
+
+    MockRead data_reads2[] = {
+      MockRead(response2.c_str()),
+      MockRead("content"),
+      MockRead(net::SYNCHRONOUS, net::OK),
+    };
+
+    StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
+                                   data_writes2, arraysize(data_writes2));
+    if (expected_retry) {
+      mock_socket_factory_.AddSocketDataProvider(&data2);
     }
 
     // Expect that we get "content" and not "Bypass message", and that there's
@@ -201,22 +214,16 @@
     ExecuteRequestExpectingContentAndHeader(
         method,
         (expect_response_body ? "content" : ""),
-        "server",
-        (expected_retry == 0 ? "proxy" : "not-proxy"),
-        has_origin,
-        expected_retry);
+        expected_retry,
+        generate_response_error);
   }
 
   // Starts a request with the given |method| and checks that the response
-  // contains |content| and the the header |header|: |value|, if |header| is
-  // non-empty. Verifies that the request's URL chain is the right length
-  // depending on whether or not a retry was expected (|expected_retry|).
+  // contains |content|.
   void ExecuteRequestExpectingContentAndHeader(const std::string& method,
                                                const std::string& content,
-                                               const std::string& header,
-                                               const std::string& value,
-                                               bool has_origin,
-                                               bool expected_retry) {
+                                               bool expected_retry,
+                                               bool expected_error) {
     TestDelegate d;
     scoped_ptr<URLRequest> r(context_->CreateRequest(
         GURL("http://www.google.com/"),
@@ -225,25 +232,23 @@
         NULL));
     r->set_method(method);
     r->SetLoadFlags(net::LOAD_NORMAL);
-    if (has_origin)
-      r->SetExtraRequestHeaderByName("Origin", "foo.com", true);
 
     r->Start();
     base::RunLoop().Run();
 
-    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
-    EXPECT_EQ(net::OK, r->status().error());
-    if (expected_retry)
-      EXPECT_EQ(2, network_delegate_->headers_received_count());
-    else
-      EXPECT_EQ(1, network_delegate_->headers_received_count());
-
-    if (!header.empty()) {
-      // We also have a server header here that isn't set by the proxy.
-      EXPECT_TRUE(r->response_headers()->HasHeaderValue(header, value));
+    if (!expected_error) {
+      EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
+      EXPECT_EQ(net::OK, r->status().error());
+      if (expected_retry)
+        EXPECT_EQ(2, network_delegate_->headers_received_count());
+      else
+        EXPECT_EQ(1, network_delegate_->headers_received_count());
+      EXPECT_EQ(content, d.data_received());
+      return;
     }
-
-    EXPECT_EQ(content, d.data_received());
+    EXPECT_EQ(net::URLRequestStatus::FAILED, r->status().status());
+    EXPECT_EQ(net::ERR_INVALID_RESPONSE, r->status().error());
+    EXPECT_EQ(0, network_delegate_->headers_received_count());
   }
 
   // Returns the key to the |ProxyRetryInfoMap|.
@@ -343,8 +348,8 @@
   const struct {
     const char* method;
     const char* first_response;
-    bool has_origin;
     bool expected_retry;
+    bool generate_response_error;
     size_t expected_bad_proxy_count;
     bool expect_response_body;
     int expected_duration;
@@ -362,6 +367,16 @@
       -1,
       BYPASS_EVENT_TYPE_MAX,
     },
+    // Response error does not result in bypass.
+    { "GET",
+      "Not an HTTP response",
+      false,
+      true,
+      0u,
+      true,
+      -1,
+      BYPASS_EVENT_TYPE_MAX,
+    },
     // Valid data reduction proxy response with older, but still valid via
     // header.
     { "GET",
@@ -394,8 +409,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=0\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -407,8 +422,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=1\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       1,
@@ -420,8 +435,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=0\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -433,8 +448,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=0\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       false,
       0,
@@ -446,8 +461,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=0\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -459,8 +474,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=0\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -472,8 +487,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=0\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -484,8 +499,8 @@
       "HTTP/1.1 500 Internal Server Error\r\n"
       "Server: proxy\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -496,8 +511,8 @@
       "HTTP/1.1 502 Internal Server Error\r\n"
       "Server: proxy\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -508,8 +523,8 @@
       "HTTP/1.1 503 Internal Server Error\r\n"
       "Server: proxy\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -519,8 +534,8 @@
     { "GET",
       "HTTP/1.1 404 Not Found\r\n"
       "Server: proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       1,
@@ -530,8 +545,8 @@
     { "GET",
       "HTTP/1.1 200 OK\r\n"
       "Server: proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -542,8 +557,8 @@
       "HTTP/1.1 200 OK\r\n"
       "Server: proxy\r\n"
       "Via: 1.0 some-other-proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       0,
@@ -581,8 +596,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block=1\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       2u,
       true,
       1,
@@ -596,8 +611,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       0u,
       true,
       0,
@@ -609,8 +624,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       0u,
       true,
       0,
@@ -622,8 +637,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       0u,
       false,
       0,
@@ -635,8 +650,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       0u,
       true,
       0,
@@ -648,8 +663,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       0u,
       true,
       0,
@@ -661,8 +676,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       0u,
       true,
       0,
@@ -692,8 +707,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: block=1, block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       2u,
       true,
       1,
@@ -707,8 +722,8 @@
       "Server: proxy\r\n"
       "Chrome-Proxy: bypass=1, block-once\r\n"
       "Via: 1.1 Chrome-Compression-Proxy\r\n\r\n",
-      false,
       true,
+      false,
       1u,
       true,
       1,
@@ -726,8 +741,8 @@
         &bypass_type);
     TestProxyFallback(tests[i].method,
                       tests[i].first_response,
-                      tests[i].has_origin,
                       tests[i].expected_retry,
+                      tests[i].generate_response_error,
                       tests[i].expected_bad_proxy_count,
                       tests[i].expect_response_body);
     EXPECT_EQ(tests[i].expected_bypass_type, usage_stats_->GetBypassType());
diff --git a/components/data_reduction_proxy_version_header.target.darwin-arm.mk b/components/data_reduction_proxy_version_header.target.darwin-arm.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.darwin-arm.mk
+++ b/components/data_reduction_proxy_version_header.target.darwin-arm.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.darwin-arm64.mk b/components/data_reduction_proxy_version_header.target.darwin-arm64.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.darwin-arm64.mk
+++ b/components/data_reduction_proxy_version_header.target.darwin-arm64.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.darwin-mips.mk b/components/data_reduction_proxy_version_header.target.darwin-mips.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.darwin-mips.mk
+++ b/components/data_reduction_proxy_version_header.target.darwin-mips.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.darwin-mips64.mk b/components/data_reduction_proxy_version_header.target.darwin-mips64.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.darwin-mips64.mk
+++ b/components/data_reduction_proxy_version_header.target.darwin-mips64.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.darwin-x86.mk b/components/data_reduction_proxy_version_header.target.darwin-x86.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.darwin-x86.mk
+++ b/components/data_reduction_proxy_version_header.target.darwin-x86.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.darwin-x86_64.mk b/components/data_reduction_proxy_version_header.target.darwin-x86_64.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.darwin-x86_64.mk
+++ b/components/data_reduction_proxy_version_header.target.darwin-x86_64.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.linux-arm.mk b/components/data_reduction_proxy_version_header.target.linux-arm.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.linux-arm.mk
+++ b/components/data_reduction_proxy_version_header.target.linux-arm.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.linux-arm64.mk b/components/data_reduction_proxy_version_header.target.linux-arm64.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.linux-arm64.mk
+++ b/components/data_reduction_proxy_version_header.target.linux-arm64.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.linux-mips.mk b/components/data_reduction_proxy_version_header.target.linux-mips.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.linux-mips.mk
+++ b/components/data_reduction_proxy_version_header.target.linux-mips.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.linux-mips64.mk b/components/data_reduction_proxy_version_header.target.linux-mips64.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.linux-mips64.mk
+++ b/components/data_reduction_proxy_version_header.target.linux-mips64.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.linux-x86.mk b/components/data_reduction_proxy_version_header.target.linux-x86.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.linux-x86.mk
+++ b/components/data_reduction_proxy_version_header.target.linux-x86.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/data_reduction_proxy_version_header.target.linux-x86_64.mk b/components/data_reduction_proxy_version_header.target.linux-x86_64.mk
index 3167295..de8667a 100644
--- a/components/data_reduction_proxy_version_header.target.linux-x86_64.mk
+++ b/components/data_reduction_proxy_version_header.target.linux-x86_64.mk
@@ -22,7 +22,7 @@
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h: $(LOCAL_PATH)/chrome/VERSION $(LOCAL_PATH)/components/data_reduction_proxy/core/common/version.h.in $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating version header file: "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h" ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.27\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common; python ../build/util/version.py -e "VERSION_FULL=\"40.0.2214.38\"" data_reduction_proxy/core/common/version.h.in "$(gyp_shared_intermediate_dir)/components/data_reduction_proxy/core/common/version.h"
 
 
 
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc
index 60fa6fd..0570e74 100644
--- a/components/password_manager/core/browser/login_database.cc
+++ b/components/password_manager/core/browser/login_database.cc
@@ -648,9 +648,10 @@
   std::string registered_domain = GetRegistryControlledDomain(signon_realm);
   PSLDomainMatchMetric psl_domain_match_metric = PSL_DOMAIN_MATCH_NONE;
   const bool should_PSL_matching_apply =
+      form.scheme == PasswordForm::SCHEME_HTML &&
       ShouldPSLDomainMatchingApply(registered_domain);
   // PSL matching only applies to HTML forms.
-  if (form.scheme == PasswordForm::SCHEME_HTML && should_PSL_matching_apply) {
+  if (should_PSL_matching_apply) {
     // We are extending the original SQL query with one that includes more
     // possible matches based on public suffix domain matching. Using a regexp
     // here is just an optimization to not have to parse all the stored entries
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc
index 5ec0e2e..f3a27f8 100644
--- a/components/password_manager/core/browser/login_database_unittest.cc
+++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -102,7 +102,7 @@
     EXPECT_TRUE(db_.GetLogins(second_non_html_auth, &result.get()));
     EXPECT_EQ(0U, result.size());
 
-    // non-html auth still matches again itself.
+    // non-html auth still matches against itself.
     EXPECT_TRUE(db_.GetLogins(non_html_auth, &result.get()));
     ASSERT_EQ(1U, result.size());
     EXPECT_EQ(result[0]->signon_realm, "http://example.com/Realm");
@@ -111,6 +111,32 @@
     db_.RemoveLoginsCreatedBetween(now, base::Time());
   }
 
+  // Checks that a form of a given |scheme|, once stored, can be successfully
+  // retrieved from the database.
+  void TestRetrievingIPAddress(const PasswordForm::Scheme& scheme) {
+    SCOPED_TRACE(testing::Message() << "scheme = " << scheme);
+    ScopedVector<PasswordForm> result;
+
+    base::Time now = base::Time::Now();
+    std::string origin("http://56.7.8.90");
+
+    PasswordForm ip_form;
+    ip_form.origin = GURL(origin);
+    ip_form.username_value = ASCIIToUTF16("test@gmail.com");
+    ip_form.password_value = ASCIIToUTF16("test");
+    ip_form.signon_realm = origin;
+    ip_form.scheme = scheme;
+    ip_form.date_created = now;
+
+    EXPECT_EQ(AddChangeForForm(ip_form), db_.AddLogin(ip_form));
+    EXPECT_TRUE(db_.GetLogins(ip_form, &result.get()));
+    ASSERT_EQ(1U, result.size());
+    EXPECT_EQ(result[0]->signon_realm, origin);
+
+    // Clear state.
+    db_.RemoveLoginsCreatedBetween(now, base::Time());
+  }
+
   base::ScopedTempDir temp_dir_;
   base::FilePath file_;
   LoginDatabase db_;
@@ -315,6 +341,22 @@
   TestNonHTMLFormPSLMatching(PasswordForm::SCHEME_OTHER);
 }
 
+TEST_F(LoginDatabaseTest, TestIPAddressMatches_HTML) {
+  TestRetrievingIPAddress(PasswordForm::SCHEME_HTML);
+}
+
+TEST_F(LoginDatabaseTest, TestIPAddressMatches_basic) {
+  TestRetrievingIPAddress(PasswordForm::SCHEME_BASIC);
+}
+
+TEST_F(LoginDatabaseTest, TestIPAddressMatches_digest) {
+  TestRetrievingIPAddress(PasswordForm::SCHEME_DIGEST);
+}
+
+TEST_F(LoginDatabaseTest, TestIPAddressMatches_other) {
+  TestRetrievingIPAddress(PasswordForm::SCHEME_OTHER);
+}
+
 TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingShouldMatchingApply) {
   std::vector<PasswordForm*> result;
 
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 4dd75b5..b4c2e22 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -257,6 +257,17 @@
       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
@@ -543,9 +554,15 @@
   // Upload credentials the first time they are saved. This data is used
   // by password generation to help determine account creation sites.
   // Blacklisted credentials will never be used, so don't upload a vote for
-  // them.
-  if (!pending_credentials_.blacklisted_by_user)
-    UploadPasswordForm(pending_credentials_.form_data, autofill::PASSWORD);
+  // them. Credentials that have been previously used (e.g. PSL matches) are
+  // checked to see if they are valid account creation forms.
+  if (!pending_credentials_.blacklisted_by_user) {
+    if (pending_credentials_.times_used == 0) {
+      UploadPasswordForm(pending_credentials_.form_data, autofill::PASSWORD);
+    } else {
+      CheckForAccountCreationForm(pending_credentials_, observed_form_);
+    }
+  }
 
   pending_credentials_.date_created = Time::Now();
   SanitizePossibleUsernames(&pending_credentials_);
@@ -604,8 +621,7 @@
     return;
   }
 
-  // Update metadata.
-  ++pending_credentials_.times_used;
+  UpdateMetadataForUsage(pending_credentials_);
 
   if (client_->IsSyncAccountCredential(
           base::UTF16ToUTF8(pending_credentials_.username_value),
@@ -619,10 +635,6 @@
 
   UpdatePreferredLoginState(password_store);
 
-  // Remove alternate usernames. At this point we assume that we have found
-  // the right username.
-  pending_credentials_.other_possible_usernames.clear();
-
   // Update the new preferred login.
   if (!selected_username_.empty()) {
     // An other possible username is selected. We set this selected username
@@ -675,6 +687,15 @@
   }
 }
 
+void PasswordFormManager::UpdateMetadataForUsage(
+    const PasswordForm& credential) {
+  ++pending_credentials_.times_used;
+
+  // Remove alternate usernames. At this point we assume that we have found
+  // the right username.
+  pending_credentials_.other_possible_usernames.clear();
+}
+
 bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
     const base::string16& username) {
   for (PasswordFormMap::const_iterator it = best_matches_.begin();
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 67ac2ea..3037ce6 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -254,6 +254,10 @@
   bool UpdatePendingCredentialsIfOtherPossibleUsername(
       const base::string16& username);
 
+  // Update state to reflect that |credential| was used. This is broken out from
+  // UpdateLogin() so that PSL matches can also be properly updated.
+  void UpdateMetadataForUsage(const autofill::PasswordForm& credential);
+
   // Converts the "ActionsTaken" fields into an int so they can be logged to
   // UMA.
   int GetActionsTaken();
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index c38ed9a..f81bfbd 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -34,6 +34,7 @@
 using ::testing::Mock;
 using ::testing::NiceMock;
 using ::testing::Return;
+using ::testing::SaveArg;
 
 namespace password_manager {
 
@@ -170,6 +171,22 @@
     saved_match_.other_possible_usernames.push_back(
         ASCIIToUTF16("test2@gmail.com"));
 
+    autofill::FormFieldData field;
+    field.label = ASCIIToUTF16("full_name");
+    field.name = ASCIIToUTF16("full_name");
+    field.form_control_type = "text";
+    saved_match_.form_data.fields.push_back(field);
+
+    field.label = ASCIIToUTF16("Email");
+    field.name = ASCIIToUTF16("Email");
+    field.form_control_type = "text";
+    saved_match_.form_data.fields.push_back(field);
+
+    field.label = ASCIIToUTF16("password");
+    field.name = ASCIIToUTF16("password");
+    field.form_control_type = "password";
+    saved_match_.form_data.fields.push_back(field);
+
     mock_store_ = new NiceMock<MockPasswordStore>();
     client_.reset(new TestPasswordManagerClient(mock_store_.get()));
   }
@@ -321,6 +338,48 @@
   EXPECT_FALSE(manager.IsPendingCredentialsPublicSuffixMatch());
 }
 
+TEST_F(PasswordFormManagerTest, PSLMatchedCredentialsMetadataUpdated) {
+  TestPasswordManagerClient client_with_store(mock_store());
+  EXPECT_CALL(*(client_with_store.mock_driver()), IsOffTheRecord())
+      .WillRepeatedly(Return(false));
+
+  TestPasswordManager manager(&client_with_store);
+  PasswordFormManager form_manager(&manager,
+                                   &client_with_store,
+                                   client_with_store.mock_driver(),
+                                   *observed_form(),
+                                   false);
+
+  // The suggestion needs to be PSL-matched.
+  saved_match()->original_signon_realm = "www.example.org";
+  SimulateMatchingPhase(&form_manager, RESULT_MATCH_FOUND);
+
+  PasswordForm submitted_form(*observed_form());
+  submitted_form.preferred = true;
+  submitted_form.username_value = saved_match()->username_value;
+  submitted_form.password_value = saved_match()->password_value;
+  submitted_form.origin = saved_match()->origin;
+  form_manager.ProvisionallySave(
+      submitted_form, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES);
+
+  PasswordForm expected_saved_form(submitted_form);
+  expected_saved_form.times_used = 1;
+  expected_saved_form.other_possible_usernames.clear();
+  expected_saved_form.form_data = saved_match()->form_data;
+  PasswordForm actual_saved_form;
+
+  EXPECT_CALL(*(client_with_store.mock_driver()->mock_autofill_manager()),
+              UploadPasswordForm(_, autofill::ACCOUNT_CREATION_PASSWORD))
+      .Times(1);
+  EXPECT_CALL(*mock_store(), AddLogin(_))
+      .WillOnce(SaveArg<0>(&actual_saved_form));
+  form_manager.Save();
+
+  // Can't verify time, so ignore it.
+  actual_saved_form.date_created = base::Time();
+  EXPECT_EQ(expected_saved_form, actual_saved_form);
+}
+
 TEST_F(PasswordFormManagerTest, TestNewLoginFromNewPasswordElement) {
   // Add a new password field to the test form. The PasswordFormManager should
   // save the password from this field, instead of the current password field.
@@ -1132,33 +1191,15 @@
   EXPECT_CALL(*client_with_store.mock_driver(), IsOffTheRecord())
       .WillRepeatedly(Return(false));
 
-  PasswordForm form(*observed_form());
-
-  autofill::FormFieldData field;
-  field.label = ASCIIToUTF16("full_name");
-  field.name = ASCIIToUTF16("full_name");
-  field.form_control_type = "text";
-  form.form_data.fields.push_back(field);
-
-  field.label = ASCIIToUTF16("Email");
-  field.name = ASCIIToUTF16("Email");
-  field.form_control_type = "text";
-  form.form_data.fields.push_back(field);
-
-  field.label = ASCIIToUTF16("password");
-  field.name = ASCIIToUTF16("password");
-  field.form_control_type = "password";
-  form.form_data.fields.push_back(field);
-
   // For newly saved passwords, upload a vote for autofill::PASSWORD.
   PasswordFormManager form_manager(&password_manager,
                                    &client_with_store,
                                    client_with_store.GetDriver(),
-                                   form,
+                                   *saved_match(),
                                    false);
   SimulateMatchingPhase(&form_manager, RESULT_NO_MATCH);
 
-  PasswordForm form_to_save(form);
+  PasswordForm form_to_save(*saved_match());
   form_to_save.preferred = true;
   form_to_save.username_value = ASCIIToUTF16("username");
   form_to_save.password_value = ASCIIToUTF16("1234");
@@ -1175,7 +1216,7 @@
   PasswordFormManager blacklist_form_manager(&password_manager,
                                              &client_with_store,
                                              client_with_store.GetDriver(),
-                                             form,
+                                             *saved_match(),
                                              false);
   SimulateMatchingPhase(&blacklist_form_manager, RESULT_NO_MATCH);
 
diff --git a/components/password_manager/core/browser/psl_matching_helper.cc b/components/password_manager/core/browser/psl_matching_helper.cc
index 69244fa..dd5a1a7 100644
--- a/components/password_manager/core/browser/psl_matching_helper.cc
+++ b/components/password_manager/core/browser/psl_matching_helper.cc
@@ -18,7 +18,8 @@
 
 bool ShouldPSLDomainMatchingApply(
     const std::string& registry_controlled_domain) {
-  return registry_controlled_domain != "google.com";
+  return !registry_controlled_domain.empty() &&
+         registry_controlled_domain != "google.com";
 }
 
 bool IsPublicSuffixDomainMatch(const std::string& url1,
@@ -29,6 +30,9 @@
   if (!gurl1.is_valid() || !gurl2.is_valid())
     return false;
 
+  if (gurl1 == gurl2)
+    return true;
+
   return gurl1.scheme() == gurl2.scheme() &&
          GetRegistryControlledDomain(gurl1) ==
              GetRegistryControlledDomain(gurl2) &&
diff --git a/components/proximity_auth/switches.cc b/components/proximity_auth/switches.cc
index ba5aab7..7472761 100644
--- a/components/proximity_auth/switches.cc
+++ b/components/proximity_auth/switches.cc
@@ -7,6 +7,12 @@
 namespace proximity_auth {
 namespace switches {
 
+// Disable Easy sign-in.
+const char kDisableEasySignin[] = "disable-easy-signin";
+
+// Disable Easy unlock.
+const char kDisableEasyUnlock[] = "disable-easy-unlock";
+
 // Enables close proximity detection. This allows the user to set a setting to
 // require very close proximity between the remote device and the local device
 // in order to unlock the local device, which trades off convenience for
diff --git a/components/proximity_auth/switches.h b/components/proximity_auth/switches.h
index 0e8fed7..9995e3e 100644
--- a/components/proximity_auth/switches.h
+++ b/components/proximity_auth/switches.h
@@ -10,6 +10,8 @@
 
 // All switches in alphabetical order. The switches should be documented
 // alongside the definition of their values in the .cc file.
+extern const char kDisableEasySignin[];
+extern const char kDisableEasyUnlock[];
 extern const char kEnableProximityDetection[];
 
 }  // namespace switches
diff --git a/content/browser/android/content_startup_flags.cc b/content/browser/android/content_startup_flags.cc
index d531dbb..7fb2b42 100644
--- a/content/browser/android/content_startup_flags.cc
+++ b/content/browser/android/content_startup_flags.cc
@@ -65,7 +65,6 @@
   parsed_command_line->AppendSwitch(switches::kInProcessGPU);
   parsed_command_line->AppendSwitch(switches::kDisableGpuShaderDiskCache);
 
-  parsed_command_line->AppendSwitch(switches::kEnableViewport);
   parsed_command_line->AppendSwitch(switches::kEnableViewportMeta);
   parsed_command_line->AppendSwitch(
       switches::kMainFrameResizesAreOrientationChanges);
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 12117bf..f9f0f4f 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -249,9 +249,9 @@
       BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
   web_contents->SetUserAgentOverride(spoofed_ua);
 
-  java_bridge_dispatcher_host_.reset(
+  java_bridge_dispatcher_host_ =
       new GinJavaBridgeDispatcherHost(web_contents,
-                                      java_bridge_retained_object_set));
+                                      java_bridge_retained_object_set);
 
   InitWebContents();
 }
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index 8a823ee..f37659c 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -341,8 +341,7 @@
   bool accessibility_enabled_;
 
   // Manages injecting Java objects.
-  scoped_ptr<GinJavaBridgeDispatcherHost>
-      java_bridge_dispatcher_host_;
+  scoped_refptr<GinJavaBridgeDispatcherHost> java_bridge_dispatcher_host_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentViewCoreImpl);
 };
diff --git a/content/browser/android/java/gin_java_bound_object.cc b/content/browser/android/java/gin_java_bound_object.cc
index 99c8b5d..527fcef 100644
--- a/content/browser/android/java/gin_java_bound_object.cc
+++ b/content/browser/android/java/gin_java_bound_object.cc
@@ -42,8 +42,8 @@
 GinJavaBoundObject* GinJavaBoundObject::CreateTransient(
     const JavaObjectWeakGlobalRef& ref,
     const base::android::JavaRef<jclass>& safe_annotation_clazz,
-    RenderFrameHost* holder) {
-  std::set<RenderFrameHost*> holders;
+    int32 holder) {
+  std::set<int32> holders;
   holders.insert(holder);
   return new GinJavaBoundObject(ref, safe_annotation_clazz, holders);
 }
@@ -61,7 +61,7 @@
 GinJavaBoundObject::GinJavaBoundObject(
     const JavaObjectWeakGlobalRef& ref,
     const base::android::JavaRef<jclass>& safe_annotation_clazz,
-    const std::set<RenderFrameHost*> holders)
+    const std::set<int32>& holders)
     : ref_(ref),
       names_count_(0),
       holders_(holders),
diff --git a/content/browser/android/java/gin_java_bound_object.h b/content/browser/android/java/gin_java_bound_object.h
index ce1d403..72fa7c6 100644
--- a/content/browser/android/java/gin_java_bound_object.h
+++ b/content/browser/android/java/gin_java_bound_object.h
@@ -10,26 +10,17 @@
 
 #include "base/android/jni_weak_ref.h"
 #include "base/android/scoped_java_ref.h"
-#include "base/id_map.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "content/browser/android/java/java_method.h"
 
 namespace content {
 
-class RenderFrameHost;
-
 class GinJavaBoundObject
     : public base::RefCountedThreadSafe<GinJavaBoundObject> {
  public:
-  // Using scoped_refptr<> as a value type is somewhat not IDMap had been
-  // designed for (it returns T* from lookups, so we have to de-ref it), but on
-  // the other hand, this allows us to manage lifetime of GinJavaBoundObject
-  // automatically.
-  typedef IDMap<scoped_refptr<GinJavaBoundObject>, IDMapOwnPointer> ObjectMap;
-  typedef ObjectMap::KeyType ObjectID;
+  typedef int32 ObjectID;
 
   static GinJavaBoundObject* CreateNamed(
       const JavaObjectWeakGlobalRef& ref,
@@ -37,8 +28,9 @@
   static GinJavaBoundObject* CreateTransient(
       const JavaObjectWeakGlobalRef& ref,
       const base::android::JavaRef<jclass>& safe_annotation_clazz,
-      RenderFrameHost* holder);
+      int32 holder);
 
+  // The following methods can be called on any thread.
   JavaObjectWeakGlobalRef& GetWeakRef() { return ref_; }
   base::android::ScopedJavaLocalRef<jobject> GetLocalRef(JNIEnv* env) {
     return ref_.get(env);
@@ -49,8 +41,8 @@
   void RemoveName() { --names_count_; }
 
   bool HasHolders() { return !holders_.empty(); }
-  void AddHolder(RenderFrameHost* holder) { holders_.insert(holder); }
-  void RemoveHolder(RenderFrameHost* holder) { holders_.erase(holder); }
+  void AddHolder(int32 holder) { holders_.insert(holder); }
+  void RemoveHolder(int32 holder) { holders_.erase(holder); }
 
   // The following methods are called on the background thread.
   std::set<std::string> GetMethodNames();
@@ -70,7 +62,7 @@
   GinJavaBoundObject(
       const JavaObjectWeakGlobalRef& ref,
       const base::android::JavaRef<jclass>& safe_annotation_clazz,
-      const std::set<RenderFrameHost*> holders);
+      const std::set<int32>& holders);
   ~GinJavaBoundObject();
 
   // The following methods are called on the background thread.
@@ -81,7 +73,7 @@
   // An object must be kept in retained_object_set_ either if it has
   // names or if it has a non-empty holders set.
   int names_count_;
-  std::set<RenderFrameHost*> holders_;
+  std::set<int32> holders_;
 
   // The following fields are accessed on the background thread.
   typedef std::multimap<std::string, linked_ptr<JavaMethod> > JavaMethodMap;
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
index c0b20b9..7255920 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -7,7 +7,9 @@
 #include "base/android/java_handler_thread.h"
 #include "base/android/jni_android.h"
 #include "base/android/scoped_java_ref.h"
+#include "base/atomic_sequence_num.h"
 #include "base/lazy_instance.h"
+#include "base/pickle.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
@@ -18,6 +20,7 @@
 #include "content/common/gin_java_bridge_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "ipc/ipc_message_utils.h"
 
@@ -38,29 +41,63 @@
   virtual ~JavaBridgeThread() {
     Stop();
   }
+  static bool CurrentlyOn();
 };
 
 base::LazyInstance<JavaBridgeThread> g_background_thread =
     LAZY_INSTANCE_INITIALIZER;
 
+// static
+bool JavaBridgeThread::CurrentlyOn() {
+  return base::MessageLoop::current() ==
+         g_background_thread.Get().message_loop();
+}
+
+// Object IDs are globally unique, so we can figure out the right
+// GinJavaBridgeDispatcherHost when dispatching messages on the background
+// thread.
+base::StaticAtomicSequenceNumber g_next_object_id;
+
 }  // namespace
 
 GinJavaBridgeDispatcherHost::GinJavaBridgeDispatcherHost(
     WebContents* web_contents,
     jobject retained_object_set)
     : WebContentsObserver(web_contents),
+      BrowserMessageFilter(GinJavaBridgeMsgStart),
+      browser_filter_added_(false),
       retained_object_set_(base::android::AttachCurrentThread(),
                            retained_object_set),
-      allow_object_contents_inspection_(true) {
+      allow_object_contents_inspection_(true),
+      current_routing_id_(MSG_ROUTING_NONE) {
   DCHECK(retained_object_set);
 }
 
 GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() {
-  DCHECK(pending_replies_.empty());
+}
+
+// GinJavaBridgeDispatcherHost gets created earlier than RenderProcessHost
+// is initialized. So we postpone installing the message filter until we know
+// that the RPH is in a good shape. Currently this means that we are calling
+// this function from any UI thread function that is about to communicate
+// with the renderer.
+// TODO(mnaganov): Redesign, so we only have a single filter for all hosts.
+void GinJavaBridgeDispatcherHost::AddBrowserFilterIfNeeded() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // Transient objects can only appear after named objects were added. Thus,
+  // we can wait until we have one, to avoid installing unnecessary filters.
+  if (!browser_filter_added_ &&
+      web_contents()->GetRenderProcessHost()->GetChannel() &&
+      !named_objects_.empty()) {
+    web_contents()->GetRenderProcessHost()->AddFilter(this);
+    browser_filter_added_ = true;
+  }
 }
 
 void GinJavaBridgeDispatcherHost::RenderFrameCreated(
     RenderFrameHost* render_frame_host) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  AddBrowserFilterIfNeeded();
   for (NamedObjectMap::const_iterator iter = named_objects_.begin();
        iter != named_objects_.end();
        ++iter) {
@@ -72,35 +109,40 @@
 void GinJavaBridgeDispatcherHost::RenderFrameDeleted(
     RenderFrameHost* render_frame_host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  IPC::Message* reply_msg = TakePendingReply(render_frame_host);
-  if (reply_msg != NULL) {
-    base::ListValue result;
-    result.Append(base::Value::CreateNullValue());
-    IPC::WriteParam(reply_msg, result);
-    IPC::WriteParam(reply_msg, kGinJavaBridgeRenderFrameDeleted);
-    render_frame_host->Send(reply_msg);
+  AddBrowserFilterIfNeeded();
+  base::AutoLock locker(objects_lock_);
+  auto iter = objects_.begin();
+  while (iter != objects_.end()) {
+    JavaObjectWeakGlobalRef ref =
+        RemoveHolderAndAdvanceLocked(render_frame_host->GetRoutingID(), &iter);
+    if (!ref.is_empty()) {
+      RemoveFromRetainedObjectSetLocked(ref);
+    }
   }
-  RemoveHolder(render_frame_host,
-               GinJavaBoundObject::ObjectMap::iterator(&objects_),
-               objects_.size());
 }
 
 GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject(
     const base::android::JavaRef<jobject>& object,
     const base::android::JavaRef<jclass>& safe_annotation_clazz,
     bool is_named,
-    RenderFrameHost* holder) {
+    int32 holder) {
+  // Can be called on any thread. Calls come from the UI thread via
+  // AddNamedObject, and from the background thread, when injected Java
+  // object's method returns a Java object.
   DCHECK(is_named || holder);
-  GinJavaBoundObject::ObjectID object_id;
   JNIEnv* env = base::android::AttachCurrentThread();
   JavaObjectWeakGlobalRef ref(env, object.obj());
-  if (is_named) {
-    object_id = objects_.Add(new scoped_refptr<GinJavaBoundObject>(
-        GinJavaBoundObject::CreateNamed(ref, safe_annotation_clazz)));
-  } else {
-    object_id = objects_.Add(new scoped_refptr<GinJavaBoundObject>(
-        GinJavaBoundObject::CreateTransient(
-            ref, safe_annotation_clazz, holder)));
+  scoped_refptr<GinJavaBoundObject> new_object =
+      is_named ? GinJavaBoundObject::CreateNamed(ref, safe_annotation_clazz)
+               : GinJavaBoundObject::CreateTransient(ref, safe_annotation_clazz,
+                                                     holder);
+  // Note that we are abusing the fact that StaticAtomicSequenceNumber
+  // uses Atomic32 as a counter, so it is guaranteed that it will not
+  // overflow our int32 IDs. IDs start from 1.
+  GinJavaBoundObject::ObjectID object_id = g_next_object_id.GetNext() + 1;
+  {
+    base::AutoLock locker(objects_lock_);
+    objects_[object_id] = new_object;
   }
 #if DCHECK_IS_ON
   {
@@ -112,6 +154,7 @@
   base::android::ScopedJavaLocalRef<jobject> retained_object_set =
         retained_object_set_.get(env);
   if (!retained_object_set.is_null()) {
+    base::AutoLock locker(objects_lock_);
     JNI_Java_HashSet_add(env, retained_object_set, object);
   }
   return object_id;
@@ -120,13 +163,14 @@
 bool GinJavaBridgeDispatcherHost::FindObjectId(
     const base::android::JavaRef<jobject>& object,
     GinJavaBoundObject::ObjectID* object_id) {
+  // Can be called on any thread.
   JNIEnv* env = base::android::AttachCurrentThread();
-  for (GinJavaBoundObject::ObjectMap::iterator it(&objects_); !it.IsAtEnd();
-       it.Advance()) {
+  base::AutoLock locker(objects_lock_);
+  for (const auto& pair : objects_) {
     if (env->IsSameObject(
             object.obj(),
-            it.GetCurrentValue()->get()->GetLocalRef(env).obj())) {
-      *object_id = it.GetCurrentKey();
+            pair.second->GetLocalRef(env).obj())) {
+      *object_id = pair.first;
       return true;
     }
   }
@@ -135,36 +179,40 @@
 
 JavaObjectWeakGlobalRef GinJavaBridgeDispatcherHost::GetObjectWeakRef(
     GinJavaBoundObject::ObjectID object_id) {
-  scoped_refptr<GinJavaBoundObject>* result = objects_.Lookup(object_id);
-  scoped_refptr<GinJavaBoundObject> object(result ? *result : NULL);
+  scoped_refptr<GinJavaBoundObject> object = FindObject(object_id);
   if (object.get())
     return object->GetWeakRef();
   else
     return JavaObjectWeakGlobalRef();
 }
 
-void GinJavaBridgeDispatcherHost::RemoveHolder(
-    RenderFrameHost* holder,
-    const GinJavaBoundObject::ObjectMap::iterator& from,
-    size_t count) {
+JavaObjectWeakGlobalRef
+GinJavaBridgeDispatcherHost::RemoveHolderAndAdvanceLocked(
+    int32 holder,
+    ObjectMap::iterator* iter_ptr) {
+  objects_lock_.AssertAcquired();
+  JavaObjectWeakGlobalRef result;
+  scoped_refptr<GinJavaBoundObject> object((*iter_ptr)->second);
+  if (!object->IsNamed()) {
+    object->RemoveHolder(holder);
+    if (!object->HasHolders()) {
+      result = object->GetWeakRef();
+      objects_.erase((*iter_ptr)++);
+    }
+  } else {
+    ++(*iter_ptr);
+  }
+  return result;
+}
+
+void GinJavaBridgeDispatcherHost::RemoveFromRetainedObjectSetLocked(
+    const JavaObjectWeakGlobalRef& ref) {
+  objects_lock_.AssertAcquired();
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> retained_object_set =
       retained_object_set_.get(env);
-  size_t i = 0;
-  for (GinJavaBoundObject::ObjectMap::iterator it(from);
-       !it.IsAtEnd() && i < count;
-       it.Advance(), ++i) {
-    scoped_refptr<GinJavaBoundObject> object(*it.GetCurrentValue());
-    if (object->IsNamed())
-      continue;
-    object->RemoveHolder(holder);
-    if (!object->HasHolders()) {
-      if (!retained_object_set.is_null()) {
-        JNI_Java_HashSet_remove(
-            env, retained_object_set, object->GetLocalRef(env));
-      }
-      objects_.Remove(it.GetCurrentKey());
-    }
+  if (!retained_object_set.is_null()) {
+    JNI_Java_HashSet_remove(env, retained_object_set, ref.get(env));
   }
 }
 
@@ -185,12 +233,14 @@
     RemoveNamedObject(iter->first);
   }
   if (existing_object) {
-    (*objects_.Lookup(object_id))->AddName();
+    base::AutoLock locker(objects_lock_);
+    objects_[object_id]->AddName();
   } else {
-    object_id = AddObject(object, safe_annotation_clazz, true, NULL);
+    object_id = AddObject(object, safe_annotation_clazz, true, 0);
   }
   named_objects_[name] = object_id;
 
+  AddBrowserFilterIfNeeded();
   web_contents()->SendToAllFrames(
       new GinJavaBridgeMsg_AddNamedObject(MSG_ROUTING_NONE, name, object_id));
 }
@@ -206,28 +256,30 @@
   // |name| is from |named_objects_| it'll be valid after the remove below.
   const std::string copied_name(name);
 
-  scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(iter->second));
-  named_objects_.erase(iter);
-  object->RemoveName();
-
-  // Not erasing from the objects map, as we can still receive method
-  // invocation requests for this object, and they should work until the
-  // java object is gone.
-  if (!object->IsNamed()) {
-    JNIEnv* env = base::android::AttachCurrentThread();
-    base::android::ScopedJavaLocalRef<jobject> retained_object_set =
-        retained_object_set_.get(env);
-    if (!retained_object_set.is_null()) {
-      JNI_Java_HashSet_remove(
-          env, retained_object_set, object->GetLocalRef(env));
-    }
+  {
+    base::AutoLock locker(objects_lock_);
+    objects_[iter->second]->RemoveName();
   }
+  named_objects_.erase(iter);
+
+  // As the object isn't going to be removed from the JavaScript side until the
+  // next page reload, calls to it must still work, thus we should continue to
+  // hold it. All the transient objects and removed named objects will be purged
+  // during the cleansing caused by DocumentAvailableInMainFrame event.
 
   web_contents()->SendToAllFrames(
       new GinJavaBridgeMsg_RemoveNamedObject(MSG_ROUTING_NONE, copied_name));
 }
 
 void GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection(bool allow) {
+  if (!JavaBridgeThread::CurrentlyOn()) {
+    g_background_thread.Get().message_loop()->task_runner()->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection,
+            this, allow));
+    return;
+  }
   allow_object_contents_inspection_ = allow;
 }
 
@@ -236,337 +288,203 @@
   // Called when the window object has been cleared in the main frame.
   // That means, all sub-frames have also been cleared, so only named
   // objects survived.
+  AddBrowserFilterIfNeeded();
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> retained_object_set =
       retained_object_set_.get(env);
+  base::AutoLock locker(objects_lock_);
   if (!retained_object_set.is_null()) {
     JNI_Java_HashSet_clear(env, retained_object_set);
   }
-
-  // We also need to add back the named objects we have so far as they
-  // should survive navigations.
-  for (GinJavaBoundObject::ObjectMap::iterator it(&objects_); !it.IsAtEnd();
-       it.Advance()) {
-    scoped_refptr<GinJavaBoundObject> object(*it.GetCurrentValue());
-    if (object->IsNamed()) {
+  auto iter = objects_.begin();
+  while (iter != objects_.end()) {
+    if (iter->second->IsNamed()) {
       if (!retained_object_set.is_null()) {
         JNI_Java_HashSet_add(
-            env, retained_object_set, object->GetLocalRef(env));
+            env, retained_object_set, iter->second->GetLocalRef(env));
       }
+      ++iter;
     } else {
-      objects_.Remove(it.GetCurrentKey());
+      objects_.erase(iter++);
     }
   }
 }
 
-namespace {
-
-// TODO(mnaganov): Implement passing of a parameter into sync message handlers.
-class MessageForwarder : public IPC::Sender {
- public:
-  MessageForwarder(GinJavaBridgeDispatcherHost* gjbdh,
-                   RenderFrameHost* render_frame_host)
-      : gjbdh_(gjbdh), render_frame_host_(render_frame_host) {}
-  void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
-                    IPC::Message* reply_msg) {
-    gjbdh_->OnGetMethods(render_frame_host_,
-                         object_id,
-                         reply_msg);
+base::TaskRunner* GinJavaBridgeDispatcherHost::OverrideTaskRunnerForMessage(
+    const IPC::Message& message) {
+  GinJavaBoundObject::ObjectID object_id = 0;
+  // TODO(mnaganov): It's very sad that we have a BrowserMessageFilter per
+  // WebView instance. We should redesign to have a filter per RPH.
+  // Check, if the object ID in the message is known to this host. If not,
+  // this is a message for some other host. As all our IPC messages from the
+  // renderer start with object ID, we just fetch it directly from the
+  // message, considering sync and async messages separately.
+  switch (message.type()) {
+    case GinJavaBridgeHostMsg_GetMethods::ID:
+    case GinJavaBridgeHostMsg_HasMethod::ID:
+    case GinJavaBridgeHostMsg_InvokeMethod::ID: {
+      DCHECK(message.is_sync());
+      PickleIterator message_reader =
+          IPC::SyncMessage::GetDataIterator(&message);
+      if (!IPC::ReadParam(&message, &message_reader, &object_id))
+        return NULL;
+      break;
+    }
+    case GinJavaBridgeHostMsg_ObjectWrapperDeleted::ID: {
+      DCHECK(!message.is_sync());
+      PickleIterator message_reader(message);
+      if (!IPC::ReadParam(&message, &message_reader, &object_id))
+        return NULL;
+      break;
+    }
+    default:
+      NOTREACHED();
+      return NULL;
   }
-  void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
-                   const std::string& method_name,
-                   IPC::Message* reply_msg) {
-    gjbdh_->OnHasMethod(render_frame_host_,
-                        object_id,
-                        method_name,
-                        reply_msg);
+  {
+    base::AutoLock locker(objects_lock_);
+    if (objects_.find(object_id) != objects_.end()) {
+        return g_background_thread.Get().message_loop()->task_runner().get();
+    }
   }
-  void OnInvokeMethod(GinJavaBoundObject::ObjectID object_id,
-                      const std::string& method_name,
-                      const base::ListValue& arguments,
-                      IPC::Message* reply_msg) {
-    gjbdh_->OnInvokeMethod(render_frame_host_,
-                           object_id,
-                           method_name,
-                           arguments,
-                           reply_msg);
-  }
-  virtual bool Send(IPC::Message* msg) override {
-    NOTREACHED();
-    return false;
-  }
- private:
-  GinJavaBridgeDispatcherHost* gjbdh_;
-  RenderFrameHost* render_frame_host_;
-};
-
+  return NULL;
 }
 
 bool GinJavaBridgeDispatcherHost::OnMessageReceived(
-    const IPC::Message& message,
-    RenderFrameHost* render_frame_host) {
-  DCHECK(render_frame_host);
+    const IPC::Message& message) {
+  // We can get here As WebContentsObserver also has OnMessageReceived,
+  // or because we have not provided a task runner in
+  // OverrideTaskRunnerForMessage. In either case, just bail out.
+  if (!JavaBridgeThread::CurrentlyOn())
+    return false;
+  SetCurrentRoutingID(message.routing_id());
   bool handled = true;
-  MessageForwarder forwarder(this, render_frame_host);
-  IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(GinJavaBridgeDispatcherHost, message,
-                                   render_frame_host)
-    IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_GetMethods,
-                                    &forwarder,
-                                    MessageForwarder::OnGetMethods)
-    IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_HasMethod,
-                                    &forwarder,
-                                    MessageForwarder::OnHasMethod)
-    IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_InvokeMethod,
-                                    &forwarder,
-                                    MessageForwarder::OnInvokeMethod)
+  IPC_BEGIN_MESSAGE_MAP(GinJavaBridgeDispatcherHost, message)
+    IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_GetMethods, OnGetMethods)
+    IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_HasMethod, OnHasMethod)
+    IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_InvokeMethod, OnInvokeMethod)
     IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_ObjectWrapperDeleted,
                         OnObjectWrapperDeleted)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
+  SetCurrentRoutingID(MSG_ROUTING_NONE);
   return handled;
 }
 
-namespace {
-
-class IsValidRenderFrameHostHelper
-    : public base::RefCounted<IsValidRenderFrameHostHelper> {
- public:
-  explicit IsValidRenderFrameHostHelper(RenderFrameHost* rfh_to_match)
-      : rfh_to_match_(rfh_to_match), rfh_found_(false) {}
-
-  bool rfh_found() { return rfh_found_; }
-
-  void OnFrame(RenderFrameHost* rfh) {
-    if (rfh_to_match_ == rfh) rfh_found_ = true;
+void GinJavaBridgeDispatcherHost::OnDestruct() const {
+  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    delete this;
+  } else {
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
   }
+}
 
- private:
-  friend class base::RefCounted<IsValidRenderFrameHostHelper>;
+int GinJavaBridgeDispatcherHost::GetCurrentRoutingID() const {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  return current_routing_id_;
+}
 
-  ~IsValidRenderFrameHostHelper() {}
+void GinJavaBridgeDispatcherHost::SetCurrentRoutingID(int32 routing_id) {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  current_routing_id_ = routing_id;
+}
 
-  RenderFrameHost* rfh_to_match_;
-  bool rfh_found_;
-
-  DISALLOW_COPY_AND_ASSIGN(IsValidRenderFrameHostHelper);
-};
-
-}  // namespace
-
-bool GinJavaBridgeDispatcherHost::IsValidRenderFrameHost(
-    RenderFrameHost* render_frame_host) {
-  scoped_refptr<IsValidRenderFrameHostHelper> helper =
-      new IsValidRenderFrameHostHelper(render_frame_host);
-  web_contents()->ForEachFrame(
-      base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper));
-  return helper->rfh_found();
+scoped_refptr<GinJavaBoundObject> GinJavaBridgeDispatcherHost::FindObject(
+    GinJavaBoundObject::ObjectID object_id) {
+  // Can be called on any thread.
+  base::AutoLock locker(objects_lock_);
+  auto iter = objects_.find(object_id);
+  if (iter != objects_.end())
+    return iter->second;
+  return NULL;
 }
 
 void GinJavaBridgeDispatcherHost::OnGetMethods(
-    RenderFrameHost* render_frame_host,
     GinJavaBoundObject::ObjectID object_id,
-    IPC::Message* reply_msg) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(render_frame_host);
-  if (!allow_object_contents_inspection_) {
-    IPC::WriteParam(reply_msg, std::set<std::string>());
-    render_frame_host->Send(reply_msg);
+    std::set<std::string>* returned_method_names) {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  if (!allow_object_contents_inspection_)
     return;
-  }
-  scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
-  if (!object.get()) {
+  scoped_refptr<GinJavaBoundObject> object = FindObject(object_id);
+  if (object.get()) {
+    *returned_method_names = object->GetMethodNames();
+  } else {
     LOG(ERROR) << "WebView: Unknown object: " << object_id;
-    IPC::WriteParam(reply_msg, std::set<std::string>());
-    render_frame_host->Send(reply_msg);
-    return;
   }
-  DCHECK(!HasPendingReply(render_frame_host));
-  pending_replies_[render_frame_host] = reply_msg;
-  base::PostTaskAndReplyWithResult(
-      g_background_thread.Get().message_loop()->message_loop_proxy().get(),
-      FROM_HERE,
-      base::Bind(&GinJavaBoundObject::GetMethodNames, object),
-      base::Bind(&GinJavaBridgeDispatcherHost::SendMethods,
-                 AsWeakPtr(),
-                 render_frame_host));
-}
-
-void GinJavaBridgeDispatcherHost::SendMethods(
-    RenderFrameHost* render_frame_host,
-    const std::set<std::string>& method_names) {
-  IPC::Message* reply_msg = TakePendingReply(render_frame_host);
-  if (!reply_msg) {
-    return;
-  }
-  IPC::WriteParam(reply_msg, method_names);
-  render_frame_host->Send(reply_msg);
 }
 
 void GinJavaBridgeDispatcherHost::OnHasMethod(
-    RenderFrameHost* render_frame_host,
     GinJavaBoundObject::ObjectID object_id,
     const std::string& method_name,
-    IPC::Message* reply_msg) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(render_frame_host);
-  scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
-  if (!object.get()) {
+    bool* result) {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  scoped_refptr<GinJavaBoundObject> object = FindObject(object_id);
+  if (object.get()) {
+    *result = object->HasMethod(method_name);
+  } else {
     LOG(ERROR) << "WebView: Unknown object: " << object_id;
-    IPC::WriteParam(reply_msg, false);
-    render_frame_host->Send(reply_msg);
-    return;
   }
-  DCHECK(!HasPendingReply(render_frame_host));
-  pending_replies_[render_frame_host] = reply_msg;
-  base::PostTaskAndReplyWithResult(
-      g_background_thread.Get().message_loop()->message_loop_proxy().get(),
-      FROM_HERE,
-      base::Bind(&GinJavaBoundObject::HasMethod, object, method_name),
-      base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply,
-                 AsWeakPtr(),
-                 render_frame_host));
-}
-
-void GinJavaBridgeDispatcherHost::SendHasMethodReply(
-    RenderFrameHost* render_frame_host,
-    bool result) {
-  IPC::Message* reply_msg = TakePendingReply(render_frame_host);
-  if (!reply_msg) {
-    return;
-  }
-  IPC::WriteParam(reply_msg, result);
-  render_frame_host->Send(reply_msg);
 }
 
 void GinJavaBridgeDispatcherHost::OnInvokeMethod(
-    RenderFrameHost* render_frame_host,
     GinJavaBoundObject::ObjectID object_id,
     const std::string& method_name,
     const base::ListValue& arguments,
-    IPC::Message* reply_msg) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(render_frame_host);
-  scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+    base::ListValue* wrapped_result,
+    content::GinJavaBridgeError* error_code) {
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  DCHECK(GetCurrentRoutingID() != MSG_ROUTING_NONE);
+  scoped_refptr<GinJavaBoundObject> object = FindObject(object_id);
   if (!object.get()) {
     LOG(ERROR) << "WebView: Unknown object: " << object_id;
-    base::ListValue result;
-    result.Append(base::Value::CreateNullValue());
-    IPC::WriteParam(reply_msg, result);
-    IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId);
-    render_frame_host->Send(reply_msg);
+    wrapped_result->Append(base::Value::CreateNullValue());
+    *error_code = kGinJavaBridgeUnknownObjectId;
     return;
   }
-  DCHECK(!HasPendingReply(render_frame_host));
-  pending_replies_[render_frame_host] = reply_msg;
   scoped_refptr<GinJavaMethodInvocationHelper> result =
       new GinJavaMethodInvocationHelper(
           make_scoped_ptr(new GinJavaBoundObjectDelegate(object)),
           method_name,
           arguments);
   result->Init(this);
-  g_background_thread.Get()
-      .message_loop()
-      ->message_loop_proxy()
-      ->PostTaskAndReply(
-          FROM_HERE,
-          base::Bind(&GinJavaMethodInvocationHelper::Invoke, result),
-          base::Bind(
-              &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult,
-              AsWeakPtr(),
-              render_frame_host,
-              result));
-}
-
-void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult(
-    RenderFrameHost* render_frame_host,
-    scoped_refptr<GinJavaMethodInvocationHelper> result) {
+  result->Invoke();
+  *error_code = result->GetInvocationError();
   if (result->HoldsPrimitiveResult()) {
-    IPC::Message* reply_msg = TakePendingReply(render_frame_host);
-    if (!reply_msg) {
-      return;
-    }
-    IPC::WriteParam(reply_msg, result->GetPrimitiveResult());
-    IPC::WriteParam(reply_msg, result->GetInvocationError());
-    render_frame_host->Send(reply_msg);
-  } else {
-    ProcessMethodInvocationObjectResult(render_frame_host, result);
-  }
-}
-
-void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult(
-    RenderFrameHost* render_frame_host,
-    scoped_refptr<GinJavaMethodInvocationHelper> result) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  if (!IsValidRenderFrameHost(render_frame_host)) {
-    // In this case, we must've already sent the reply when the render frame
-    // was destroyed.
-    DCHECK(!HasPendingReply(render_frame_host));
-    return;
-  }
-
-  base::ListValue wrapped_result;
-  if (!result->GetObjectResult().is_null()) {
+    scoped_ptr<base::ListValue> result_copy(
+        result->GetPrimitiveResult().DeepCopy());
+    wrapped_result->Swap(result_copy.get());
+  } else if (!result->GetObjectResult().is_null()) {
     GinJavaBoundObject::ObjectID returned_object_id;
     if (FindObjectId(result->GetObjectResult(), &returned_object_id)) {
-      (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host);
+      base::AutoLock locker(objects_lock_);
+      objects_[returned_object_id]->AddHolder(GetCurrentRoutingID());
     } else {
       returned_object_id = AddObject(result->GetObjectResult(),
                                      result->GetSafeAnnotationClass(),
                                      false,
-                                     render_frame_host);
+                                     GetCurrentRoutingID());
     }
-    wrapped_result.Append(
+    wrapped_result->Append(
         GinJavaBridgeValue::CreateObjectIDValue(
             returned_object_id).release());
   } else {
-    wrapped_result.Append(base::Value::CreateNullValue());
+    wrapped_result->Append(base::Value::CreateNullValue());
   }
-  IPC::Message* reply_msg = TakePendingReply(render_frame_host);
-  if (!reply_msg) {
-    return;
-  }
-  IPC::WriteParam(reply_msg, wrapped_result);
-  IPC::WriteParam(reply_msg, result->GetInvocationError());
-  render_frame_host->Send(reply_msg);
 }
 
 void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
-    RenderFrameHost* render_frame_host,
     GinJavaBoundObject::ObjectID object_id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  DCHECK(render_frame_host);
-  if (objects_.Lookup(object_id)) {
-    GinJavaBoundObject::ObjectMap::iterator iter(&objects_);
-    while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id)
-      iter.Advance();
-    DCHECK(!iter.IsAtEnd());
-    RemoveHolder(render_frame_host, iter, 1);
+  DCHECK(JavaBridgeThread::CurrentlyOn());
+  DCHECK(GetCurrentRoutingID() != MSG_ROUTING_NONE);
+  base::AutoLock locker(objects_lock_);
+  auto iter = objects_.find(object_id);
+  if (iter == objects_.end())
+    return;
+  JavaObjectWeakGlobalRef ref =
+      RemoveHolderAndAdvanceLocked(GetCurrentRoutingID(), &iter);
+  if (!ref.is_empty()) {
+    RemoveFromRetainedObjectSetLocked(ref);
   }
 }
 
-IPC::Message* GinJavaBridgeDispatcherHost::TakePendingReply(
-    RenderFrameHost* render_frame_host) {
-  if (!IsValidRenderFrameHost(render_frame_host)) {
-    DCHECK(!HasPendingReply(render_frame_host));
-    return NULL;
-  }
-
-  PendingReplyMap::iterator it = pending_replies_.find(render_frame_host);
-  // There may be no pending reply if we're called from RenderFrameDeleted and
-  // we already sent the reply through the regular route.
-  if (it == pending_replies_.end()) {
-    return NULL;
-  }
-
-  IPC::Message* reply_msg = it->second;
-  pending_replies_.erase(it);
-  return reply_msg;
-}
-
-bool GinJavaBridgeDispatcherHost::HasPendingReply(
-    RenderFrameHost* render_frame_host) const {
-  return pending_replies_.find(render_frame_host) != pending_replies_.end();
-}
-
 }  // namespace content
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.h b/content/browser/android/java/gin_java_bridge_dispatcher_host.h
index c57ba26..56fddee 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.h
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.h
@@ -12,8 +12,10 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
 #include "content/browser/android/java/gin_java_bound_object.h"
 #include "content/browser/android/java/gin_java_method_invocation_helper.h"
+#include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/web_contents_observer.h"
 
 namespace base {
@@ -31,14 +33,13 @@
 // proxy object is created in the renderer. An instance of this class exists
 // for each RenderFrameHost.
 class GinJavaBridgeDispatcherHost
-    : public base::SupportsWeakPtr<GinJavaBridgeDispatcherHost>,
-      public WebContentsObserver,
+    : public WebContentsObserver,
+      public BrowserMessageFilter,
       public GinJavaMethodInvocationHelper::DispatcherDelegate {
  public:
 
   GinJavaBridgeDispatcherHost(WebContents* web_contents,
                               jobject retained_object_set);
-  virtual ~GinJavaBridgeDispatcherHost();
 
   void AddNamedObject(
       const std::string& name,
@@ -48,56 +49,68 @@
   void SetAllowObjectContentsInspection(bool allow);
 
   // WebContentsObserver
-  virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
-  virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
-  virtual void DocumentAvailableInMainFrame() override;
-  virtual bool OnMessageReceived(const IPC::Message& message,
-                                 RenderFrameHost* render_frame_host) override;
+  void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
+  void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+  void DocumentAvailableInMainFrame() override;
+
+  // BrowserMessageFilter
+  using BrowserMessageFilter::Send;
+  void OnDestruct() const override;
+  bool OnMessageReceived(const IPC::Message& message) override;
+  base::TaskRunner* OverrideTaskRunnerForMessage(
+      const IPC::Message& message) override;
 
   // GinJavaMethodInvocationHelper::DispatcherDelegate
-  virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
+  JavaObjectWeakGlobalRef GetObjectWeakRef(
       GinJavaBoundObject::ObjectID object_id) override;
 
-  void OnGetMethods(RenderFrameHost* render_frame_host,
-                    GinJavaBoundObject::ObjectID object_id,
-                    IPC::Message* reply_msg);
-  void OnHasMethod(RenderFrameHost* render_frame_host,
-                   GinJavaBoundObject::ObjectID object_id,
-                   const std::string& method_name,
-                   IPC::Message* reply_msg);
-  void OnInvokeMethod(RenderFrameHost* render_frame_host,
-                      GinJavaBoundObject::ObjectID object_id,
-                      const std::string& method_name,
-                      const base::ListValue& arguments,
-                      IPC::Message* reply_msg);
-
  private:
-  void OnObjectWrapperDeleted(RenderFrameHost* render_frame_host,
-                              GinJavaBoundObject::ObjectID object_id);
+  friend class BrowserThread;
+  friend class base::DeleteHelper<GinJavaBridgeDispatcherHost>;
 
-  bool IsValidRenderFrameHost(RenderFrameHost* render_frame_host);
-  void SendMethods(RenderFrameHost* render_frame_host,
-                   const std::set<std::string>& method_names);
-  void SendHasMethodReply(RenderFrameHost* render_frame_host,
-                          bool result);
-  void ProcessMethodInvocationResult(
-      RenderFrameHost* render_frame_host,
-      scoped_refptr<GinJavaMethodInvocationHelper> result);
-  void ProcessMethodInvocationObjectResult(
-      RenderFrameHost* render_frame_host,
-      scoped_refptr<GinJavaMethodInvocationHelper> result);
+  typedef std::map<GinJavaBoundObject::ObjectID,
+                   scoped_refptr<GinJavaBoundObject>> ObjectMap;
+
+  ~GinJavaBridgeDispatcherHost() override;
+
+  void AddBrowserFilterIfNeeded();
+
+  // Run on any thread.
   GinJavaBoundObject::ObjectID AddObject(
       const base::android::JavaRef<jobject>& object,
       const base::android::JavaRef<jclass>& safe_annotation_clazz,
       bool is_named,
-      RenderFrameHost* holder);
+      int32 holder);
+  scoped_refptr<GinJavaBoundObject> FindObject(
+      GinJavaBoundObject::ObjectID object_id);
   bool FindObjectId(const base::android::JavaRef<jobject>& object,
                     GinJavaBoundObject::ObjectID* object_id);
-  void RemoveHolder(RenderFrameHost* holder,
-                    const GinJavaBoundObject::ObjectMap::iterator& from,
-                    size_t count);
-  bool HasPendingReply(RenderFrameHost* render_frame_host) const;
-  IPC::Message* TakePendingReply(RenderFrameHost* render_frame_host);
+  void RemoveFromRetainedObjectSetLocked(const JavaObjectWeakGlobalRef& ref);
+  JavaObjectWeakGlobalRef RemoveHolderAndAdvanceLocked(
+      int32 holder,
+      ObjectMap::iterator* iter_ptr);
+
+  // Run on the background thread.
+  void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
+                    std::set<std::string>* returned_method_names);
+  void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
+                   const std::string& method_name,
+                   bool* result);
+  void OnInvokeMethod(GinJavaBoundObject::ObjectID object_id,
+                      const std::string& method_name,
+                      const base::ListValue& arguments,
+                      base::ListValue* result,
+                      content::GinJavaBridgeError* error_code);
+  void OnObjectWrapperDeleted(GinJavaBoundObject::ObjectID object_id);
+  int GetCurrentRoutingID() const;
+  void SetCurrentRoutingID(int routing_id);
+
+  bool browser_filter_added_;
+
+  typedef std::map<std::string, GinJavaBoundObject::ObjectID> NamedObjectMap;
+  NamedObjectMap named_objects_;
+
+  // The following objects are used on both threads, so locking must be used.
 
   // Every time a GinJavaBoundObject backed by a real Java object is
   // created/destroyed, we insert/remove a strong ref to that Java object into
@@ -106,17 +119,15 @@
   // and defined in Java so that pushing refs into it does not create new GC
   // roots that would prevent ContentViewCore from being garbage collected.
   JavaObjectWeakGlobalRef retained_object_set_;
-  bool allow_object_contents_inspection_;
-  GinJavaBoundObject::ObjectMap objects_;
-  typedef std::map<std::string, GinJavaBoundObject::ObjectID> NamedObjectMap;
-  NamedObjectMap named_objects_;
+  // Note that retained_object_set_ does not need to be consistent
+  // with objects_.
+  ObjectMap objects_;
+  base::Lock objects_lock_;
 
-  // Keep track of pending calls out to Java such that we can send a synchronous
-  // reply to the renderer waiting on the response should the RenderFrame be
-  // destroyed while the reply is pending.
-  // Only used on the UI thread.
-  typedef std::map<RenderFrameHost*, IPC::Message*> PendingReplyMap;
-  PendingReplyMap pending_replies_;
+  // The following objects are only used on the background thread.
+  bool allow_object_contents_inspection_;
+  // The routing id of the RenderFrameHost whose request we are processing.
+  int32 current_routing_id_;
 
   DISALLOW_COPY_AND_ASSIGN(GinJavaBridgeDispatcherHost);
 };
diff --git a/content/browser/android/java/gin_java_method_invocation_helper.h b/content/browser/android/java/gin_java_method_invocation_helper.h
index 014e311..f7bdd57 100644
--- a/content/browser/android/java/gin_java_method_invocation_helper.h
+++ b/content/browser/android/java/gin_java_method_invocation_helper.h
@@ -20,13 +20,10 @@
 
 class JavaMethod;
 
-// Instances of this class are created and initialized on the UI thread, do
-// their work on the background thread, and then again examined on the UI
-// thread. They don't work on both threads simultaneously, though.
+// Instances of this class are created and used on the background thread.
 class CONTENT_EXPORT GinJavaMethodInvocationHelper
     : public base::RefCountedThreadSafe<GinJavaMethodInvocationHelper> {
  public:
-  // DispatcherDelegate is used on the UI thread
   class DispatcherDelegate {
    public:
     DispatcherDelegate() {}
@@ -38,7 +35,6 @@
     DISALLOW_COPY_AND_ASSIGN(DispatcherDelegate);
   };
 
-  // ObjectDelegate is used in the background thread
   class ObjectDelegate {
    public:
     ObjectDelegate() {}
@@ -61,10 +57,8 @@
                                 const base::ListValue& arguments);
   void Init(DispatcherDelegate* dispatcher);
 
-  // Called on the background thread
   void Invoke();
 
-  // Called on the UI thread
   bool HoldsPrimitiveResult();
   const base::ListValue& GetPrimitiveResult();
   const base::android::JavaRef<jobject>& GetObjectResult();
@@ -75,7 +69,6 @@
   friend class base::RefCountedThreadSafe<GinJavaMethodInvocationHelper>;
   ~GinJavaMethodInvocationHelper();
 
-  // Called on the UI thread
   void BuildObjectRefsFromListValue(DispatcherDelegate* dispatcher,
                                     const base::Value* list_value);
   void BuildObjectRefsFromDictionaryValue(DispatcherDelegate* dispatcher,
@@ -84,7 +77,6 @@
   bool AppendObjectRef(DispatcherDelegate* dispatcher,
                        const base::Value* raw_value);
 
-  // Called on the background thread.
   void InvokeMethod(jobject object,
                     jclass clazz,
                     const JavaType& return_type,
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc
index 5dbaed1..1e39486 100644
--- a/content/browser/compositor/delegated_frame_host.cc
+++ b/content/browser/compositor/delegated_frame_host.cc
@@ -138,7 +138,7 @@
   if (resize_lock_)
     return false;
 
-  if (host->should_auto_resize())
+  if (host->auto_resize_enabled())
     return false;
 
   gfx::Size desired_size = client_->DesiredFrameSize();
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 26ecf1d..b8e3a9d 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -756,6 +756,16 @@
   return handler.Pass();
 }
 
+void ResourceDispatcherHostImpl::ClearSSLClientAuthHandlerForRequest(
+    net::URLRequest* request) {
+  ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
+  if (info) {
+    ResourceLoader* loader = GetLoader(info->GetGlobalRequestID());
+    if (loader)
+      loader->ClearSSLClientAuthHandler();
+  }
+}
+
 ResourceDispatcherHostLoginDelegate*
 ResourceDispatcherHostImpl::CreateLoginDelegate(
     ResourceLoader* loader,
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index a96af55..0abee9d 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -244,6 +244,8 @@
       ResourceResponse* response,
       std::string* payload);
 
+  void ClearSSLClientAuthHandlerForRequest(net::URLRequest* request);
+
   ResourceScheduler* scheduler() { return scheduler_.get(); }
 
   // Called by a ResourceHandler when it's ready to start reading data and
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index eae75eb..c9c24d0 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -96,7 +96,8 @@
 ResourceLoader::~ResourceLoader() {
   if (login_delegate_.get())
     login_delegate_->OnRequestCancelled();
-  ssl_client_auth_handler_.reset();
+  if (ssl_client_auth_handler_.get())
+    ssl_client_auth_handler_->OnRequestCancelled();
 
   // Run ResourceHandler destructor before we tear-down the rest of our state
   // as the ResourceHandler may want to inspect the URLRequest and other state.
@@ -196,6 +197,10 @@
   login_delegate_ = NULL;
 }
 
+void ResourceLoader::ClearSSLClientAuthHandler() {
+  ssl_client_auth_handler_ = NULL;
+}
+
 void ResourceLoader::OnUploadProgressACK() {
   waiting_for_upload_progress_ack_ = false;
 }
@@ -268,14 +273,12 @@
     return;
   }
 
-  DCHECK(!ssl_client_auth_handler_)
+  DCHECK(!ssl_client_auth_handler_.get())
       << "OnCertificateRequested called with ssl_client_auth_handler pending";
-  ssl_client_auth_handler_.reset(new SSLClientAuthHandler(
+  ssl_client_auth_handler_ = new SSLClientAuthHandler(
       GetRequestInfo()->GetContext()->CreateClientCertStore(),
       request_.get(),
-      cert_info,
-      base::Bind(&ResourceLoader::ContinueWithCertificate,
-                 weak_ptr_factory_.GetWeakPtr())));
+      cert_info);
   ssl_client_auth_handler_->SelectCertificate();
 }
 
@@ -492,7 +495,10 @@
     login_delegate_->OnRequestCancelled();
     login_delegate_ = NULL;
   }
-  ssl_client_auth_handler_.reset();
+  if (ssl_client_auth_handler_.get()) {
+    ssl_client_auth_handler_->OnRequestCancelled();
+    ssl_client_auth_handler_ = NULL;
+  }
 
   request_->CancelWithError(error);
 
@@ -708,9 +714,4 @@
   }
 }
 
-void ResourceLoader::ContinueWithCertificate(net::X509Certificate* cert) {
-  ssl_client_auth_handler_.reset();
-  request_->ContinueWithCertificate(cert);
-}
-
 }  // namespace content
diff --git a/content/browser/loader/resource_loader.h b/content/browser/loader/resource_loader.h
index d740ec0..b5c8b8a 100644
--- a/content/browser/loader/resource_loader.h
+++ b/content/browser/loader/resource_loader.h
@@ -15,10 +15,6 @@
 #include "content/public/common/signed_certificate_timestamp_id_and_status.h"
 #include "net/url_request/url_request.h"
 
-namespace net {
-class X509Certificate;
-}
-
 namespace content {
 class ResourceDispatcherHostLoginDelegate;
 class ResourceLoaderDelegate;
@@ -50,6 +46,7 @@
   ResourceRequestInfoImpl* GetRequestInfo();
 
   void ClearLoginDelegate();
+  void ClearSSLClientAuthHandler();
 
   // IPC message handlers:
   void OnUploadProgressACK();
@@ -102,7 +99,6 @@
   void ResponseCompleted();
   void CallDidFinishLoading();
   void RecordHistograms();
-  void ContinueWithCertificate(net::X509Certificate* cert);
 
   bool is_deferred() const { return deferred_stage_ != DEFERRED_NONE; }
 
@@ -133,7 +129,7 @@
   ResourceLoaderDelegate* delegate_;
 
   scoped_refptr<ResourceDispatcherHostLoginDelegate> login_delegate_;
-  scoped_ptr<SSLClientAuthHandler> ssl_client_auth_handler_;
+  scoped_refptr<SSLClientAuthHandler> ssl_client_auth_handler_;
 
   uint64 last_upload_position_;
   bool waiting_for_upload_progress_ack_;
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc
index 635f566..a24305c 100644
--- a/content/browser/loader/resource_loader_unittest.cc
+++ b/content/browser/loader/resource_loader_unittest.cc
@@ -231,6 +231,7 @@
   void SelectClientCertificate(
       int render_process_id,
       int render_view_id,
+      const net::HttpNetworkSession* network_session,
       net::SSLCertRequestInfo* cert_request_info,
       const base::Callback<void(net::X509Certificate*)>& callback) override {
     ++call_count_;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 5d8ecc8..fdca42d 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -74,11 +74,6 @@
   }
 
   virtual void SwapBuffers(cc::CompositorFrame* frame) override {
-    for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
-      frame->metadata.latency_info[i].AddLatencyNumber(
-          ui::INPUT_EVENT_BROWSER_SWAP_BUFFER_COMPONENT, 0, 0);
-    }
-
     GetCommandBufferProxy()->SetLatencyInfo(frame->metadata.latency_info);
     DCHECK(frame->gl_frame_data->sub_buffer_rect ==
            gfx::Rect(frame->gl_frame_data->size));
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index be30e92..c582a6e 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1126,6 +1126,7 @@
     switches::kEnableGPUClientLogging,
     switches::kEnableGpuClientTracing,
     switches::kEnableGPUServiceLogging,
+    switches::kEnableLinkDisambiguationPopup,
     switches::kEnableLowResTiling,
     switches::kEnableInbandTextTracks,
     switches::kEnableLCDText,
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 01a5e1b..dba2fa0 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -289,9 +289,14 @@
   params.never_visible = delegate_->IsNeverVisible();
   params.window_was_created_with_opener = window_was_created_with_opener;
   params.next_page_id = next_page_id;
-  GetWebScreenInfo(&params.screen_info);
+  params.enable_auto_resize = auto_resize_enabled();
+  params.min_size = min_size_for_auto_resize();
+  params.max_size = max_size_for_auto_resize();
+  GetResizeParams(&params.initial_size);
 
-  Send(new ViewMsg_New(params));
+  if (!Send(new ViewMsg_New(params)))
+    return false;
+  SetInitialRenderSizeParams(params.initial_size);
 
   // If it's enabled, tell the renderer to set up the Javascript bindings for
   // sending messages back to the browser.
@@ -1378,12 +1383,12 @@
 
 void RenderViewHostImpl::EnableAutoResize(const gfx::Size& min_size,
                                           const gfx::Size& max_size) {
-  SetShouldAutoResize(true);
+  SetAutoResize(true, min_size, max_size);
   Send(new ViewMsg_EnableAutoResize(GetRoutingID(), min_size, max_size));
 }
 
 void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
-  SetShouldAutoResize(false);
+  SetAutoResize(false, gfx::Size(), gfx::Size());
   Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
   if (!new_size.IsEmpty())
     GetView()->SetSize(new_size);
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 9a1d709..6363c14 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -89,10 +89,6 @@
 
 bool g_check_for_pending_resize_ack = true;
 
-const size_t kBrowserCompositeLatencyHistorySize = 60;
-const double kBrowserCompositeLatencyEstimationPercentile = 90.0;
-const double kBrowserCompositeLatencyEstimationSlack = 1.1;
-
 typedef std::pair<int32, int32> RenderWidgetHostID;
 typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
     RoutingIDWidgetMap;
@@ -167,12 +163,10 @@
       surface_id_(0),
       is_loading_(false),
       is_hidden_(hidden),
-      is_fullscreen_(false),
       repaint_ack_pending_(false),
       resize_ack_pending_(false),
       screen_info_out_of_date_(false),
-      top_controls_layout_height_(0.f),
-      should_auto_resize_(false),
+      auto_resize_enabled_(false),
       waiting_for_screen_rects_ack_(false),
       needs_repainting_on_restore_(false),
       is_unresponsive_(false),
@@ -189,7 +183,6 @@
       has_touch_handler_(false),
       last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32),
       next_browser_snapshot_id_(1),
-      browser_composite_latency_history_(kBrowserCompositeLatencyHistorySize),
       weak_factory_(this) {
   CHECK(delegate_);
   if (routing_id_ == MSG_ROUTING_NONE) {
@@ -362,7 +355,8 @@
         "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
   }
   repaint_ack_pending_ = false;
-  last_requested_size_.SetSize(0, 0);
+  if (old_resize_params_)
+    old_resize_params_->new_size = gfx::Size();
 }
 
 void RenderWidgetHostImpl::SendScreenRects() {
@@ -564,61 +558,80 @@
   WasResized();
 }
 
-void RenderWidgetHostImpl::WasResized() {
-  // Skip if the |delegate_| has already been detached because
-  // it's web contents is being deleted.
-  if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
-      !renderer_initialized_ || should_auto_resize_ || !delegate_) {
-    return;
-  }
-
-  gfx::Size new_size(view_->GetRequestedRendererSize());
-
-  gfx::Size old_physical_backing_size = physical_backing_size_;
-  physical_backing_size_ = view_->GetPhysicalBackingSize();
-  bool was_fullscreen = is_fullscreen_;
-  is_fullscreen_ = IsFullscreen();
-  float old_top_controls_layout_height =
-      top_controls_layout_height_;
-  top_controls_layout_height_ =
-      view_->GetTopControlsLayoutHeight();
-  gfx::Size old_visible_viewport_size = visible_viewport_size_;
-  visible_viewport_size_ = view_->GetVisibleViewportSize();
-
-  bool size_changed = new_size != last_requested_size_;
-  bool side_payload_changed =
-      screen_info_out_of_date_ ||
-      old_physical_backing_size != physical_backing_size_ ||
-      was_fullscreen != is_fullscreen_ ||
-      old_top_controls_layout_height !=
-          top_controls_layout_height_ ||
-      old_visible_viewport_size != visible_viewport_size_;
-
-  if (!size_changed && !side_payload_changed)
-    return;
+void RenderWidgetHostImpl::GetResizeParams(
+    ViewMsg_Resize_Params* resize_params) {
+  *resize_params = ViewMsg_Resize_Params();
 
   if (!screen_info_) {
     screen_info_.reset(new blink::WebScreenInfo);
     GetWebScreenInfo(screen_info_.get());
   }
+  resize_params->screen_info = *screen_info_;
+  resize_params->resizer_rect = GetRootWindowResizerRect();
+
+  if (view_) {
+    resize_params->new_size = view_->GetRequestedRendererSize();
+    resize_params->physical_backing_size = view_->GetPhysicalBackingSize();
+    resize_params->top_controls_layout_height =
+        view_->GetTopControlsLayoutHeight();
+    resize_params->visible_viewport_size = view_->GetVisibleViewportSize();
+    resize_params->is_fullscreen = IsFullscreen();
+  }
+}
+
+void RenderWidgetHostImpl::SetInitialRenderSizeParams(
+    const ViewMsg_Resize_Params& resize_params) {
+  // We don't expect to receive an ACK when the requested size or the physical
+  // backing size is empty, or when the main viewport size didn't change.
+  if (!resize_params.new_size.IsEmpty() &&
+      !resize_params.physical_backing_size.IsEmpty()) {
+    resize_ack_pending_ = g_check_for_pending_resize_ack;
+  }
+
+  old_resize_params_ =
+      make_scoped_ptr(new ViewMsg_Resize_Params(resize_params));
+}
+
+void RenderWidgetHostImpl::WasResized() {
+  // Skip if the |delegate_| has already been detached because
+  // it's web contents is being deleted.
+  if (resize_ack_pending_ || !process_->HasConnection() || !view_ ||
+      !renderer_initialized_ || auto_resize_enabled_ || !delegate_) {
+    return;
+  }
+
+  bool size_changed = true;
+  bool side_payload_changed = screen_info_out_of_date_;
+  scoped_ptr<ViewMsg_Resize_Params> params(new ViewMsg_Resize_Params);
+
+  GetResizeParams(params.get());
+  if (old_resize_params_) {
+    size_changed = old_resize_params_->new_size != params->new_size;
+    side_payload_changed =
+        side_payload_changed ||
+        old_resize_params_->physical_backing_size !=
+            params->physical_backing_size ||
+        old_resize_params_->is_fullscreen != params->is_fullscreen ||
+        old_resize_params_->top_controls_layout_height !=
+            params->top_controls_layout_height ||
+        old_resize_params_->visible_viewport_size !=
+            params->visible_viewport_size;
+  }
+
+  if (!size_changed && !side_payload_changed)
+    return;
 
   // We don't expect to receive an ACK when the requested size or the physical
   // backing size is empty, or when the main viewport size didn't change.
-  if (!new_size.IsEmpty() && !physical_backing_size_.IsEmpty() && size_changed)
+  if (!params->new_size.IsEmpty() && !params->physical_backing_size.IsEmpty() &&
+      size_changed) {
     resize_ack_pending_ = g_check_for_pending_resize_ack;
+  }
 
-  ViewMsg_Resize_Params params;
-  params.screen_info = *screen_info_;
-  params.new_size = new_size;
-  params.physical_backing_size = physical_backing_size_;
-  params.top_controls_layout_height = top_controls_layout_height_;
-  params.visible_viewport_size = visible_viewport_size_;
-  params.resizer_rect = GetRootWindowResizerRect();
-  params.is_fullscreen = is_fullscreen_;
-  if (!Send(new ViewMsg_Resize(routing_id_, params))) {
+  if (!Send(new ViewMsg_Resize(routing_id_, *params))) {
     resize_ack_pending_ = false;
   } else {
-    last_requested_size_ = new_size;
+    old_resize_params_.swap(params);
   }
 }
 
@@ -746,7 +759,7 @@
   // size of the view_. (For auto-sized views, current_size_ is updated during
   // UpdateRect messages.)
   gfx::Size view_size = current_size_;
-  if (!should_auto_resize_) {
+  if (!auto_resize_enabled_) {
     // Get the desired size from the current view bounds.
     gfx::Rect view_rect = view_->GetViewBounds();
     if (view_rect.IsEmpty())
@@ -800,7 +813,7 @@
 
       // For auto-resized views, current_size_ determines the view_size and it
       // may have changed during the handling of an UpdateRect message.
-      if (should_auto_resize_)
+      if (auto_resize_enabled_)
         view_size = current_size_;
 
       // Break now if we got a backing store or accelerated surface of the
@@ -1380,8 +1393,12 @@
   return false;
 }
 
-void RenderWidgetHostImpl::SetShouldAutoResize(bool enable) {
-  should_auto_resize_ = enable;
+void RenderWidgetHostImpl::SetAutoResize(bool enable,
+                                         const gfx::Size& min_size,
+                                         const gfx::Size& max_size) {
+  auto_resize_enabled_ = enable;
+  min_size_for_auto_resize_ = min_size;
+  max_size_for_auto_resize_ = max_size;
 }
 
 void RenderWidgetHostImpl::Destroy() {
@@ -1505,11 +1522,6 @@
   input_router_->OnViewUpdated(
       GetInputRouterViewFlagsFromCompositorFrameMetadata(frame->metadata));
 
-  for (size_t i = 0; i < frame->metadata.latency_info.size(); ++i) {
-    frame->metadata.latency_info[i].AddLatencyNumber(
-        ui::INPUT_EVENT_BROWSER_COMPOSITE_COMPONENT, 0, 0);
-  }
-
   if (view_) {
     view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
     view_->DidReceiveRendererFrame();
@@ -1581,7 +1593,7 @@
 
   DidUpdateBackingStore(params, paint_start);
 
-  if (should_auto_resize_) {
+  if (auto_resize_enabled_) {
     bool post_callback = new_auto_size_.IsEmpty();
     new_auto_size_ = params.view_size;
     if (post_callback) {
@@ -2073,7 +2085,7 @@
   // indicate that no callback is in progress (i.e. without this line
   // DelayedAutoResized will not get called again).
   new_auto_size_.SetSize(0, 0);
-  if (!should_auto_resize_)
+  if (!auto_resize_enabled_)
     return;
 
   OnRenderAutoResized(new_size);
@@ -2215,21 +2227,6 @@
           100);
     }
   }
-
-  ui::LatencyInfo::LatencyComponent gpu_swap_component;
-  if (!latency_info.FindLatency(
-          ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, &gpu_swap_component)) {
-    return;
-  }
-
-  ui::LatencyInfo::LatencyComponent composite_component;
-  if (latency_info.FindLatency(ui::INPUT_EVENT_BROWSER_COMPOSITE_COMPONENT,
-                               0,
-                               &composite_component)) {
-    base::TimeDelta delta =
-        gpu_swap_component.event_time - composite_component.event_time;
-    browser_composite_latency_history_.InsertSample(delta);
-  }
 }
 
 void RenderWidgetHostImpl::DidReceiveRendererFrame() {
@@ -2403,17 +2400,6 @@
       delegate_->GetOrCreateRootBrowserAccessibilityManager() : NULL;
 }
 
-base::TimeDelta RenderWidgetHostImpl::GetEstimatedBrowserCompositeTime() {
-  // TODO(orglofch) remove lower bound on estimate once we're sure it won't
-  // cause regressions
-  return std::max(
-      browser_composite_latency_history_.Percentile(
-          kBrowserCompositeLatencyEstimationPercentile) *
-          kBrowserCompositeLatencyEstimationSlack,
-      base::TimeDelta::FromMicroseconds(
-          (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60)));
-}
-
 #if defined(OS_WIN)
 gfx::NativeViewAccessible
     RenderWidgetHostImpl::GetParentNativeViewAccessible() {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 71aa04f..2c28134 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -23,7 +23,6 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
-#include "cc/base/rolling_time_delta_history.h"
 #include "cc/resources/shared_bitmap.h"
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/browser/renderer_host/input/input_ack_handler.h"
@@ -46,6 +45,7 @@
 struct ViewHostMsg_SelectionBounds_Params;
 struct ViewHostMsg_TextInputState_Params;
 struct ViewHostMsg_UpdateRect_Params;
+struct ViewMsg_Resize_Params;
 
 namespace base {
 class TimeTicks;
@@ -435,7 +435,17 @@
 
   // Indicates whether the renderer drives the RenderWidgetHosts's size or the
   // other way around.
-  bool should_auto_resize() { return should_auto_resize_; }
+  bool auto_resize_enabled() { return auto_resize_enabled_; }
+
+  // The minimum size of this renderer when auto-resize is enabled.
+  const gfx::Size& min_size_for_auto_resize() const {
+    return min_size_for_auto_resize_;
+  }
+
+  // The maximum size of this renderer when auto-resize is enabled.
+  const gfx::Size& max_size_for_auto_resize() const {
+    return max_size_for_auto_resize_;
+  }
 
   void FrameSwapped(const ui::LatencyInfo& latency_info);
   void DidReceiveRendererFrame();
@@ -470,8 +480,6 @@
   // or create it if it doesn't already exist.
   BrowserAccessibilityManager* GetOrCreateRootBrowserAccessibilityManager();
 
-  base::TimeDelta GetEstimatedBrowserCompositeTime();
-
 #if defined(OS_WIN)
   gfx::NativeViewAccessible GetParentNativeViewAccessible();
 #endif
@@ -543,7 +551,16 @@
 
   // Indicates if the render widget host should track the render widget's size
   // as opposed to visa versa.
-  void SetShouldAutoResize(bool enable);
+  void SetAutoResize(bool enable,
+                     const gfx::Size& min_size,
+                     const gfx::Size& max_size);
+
+  // Fills in the |resize_params| struct.
+  void GetResizeParams(ViewMsg_Resize_Params* resize_params);
+
+  // Sets the |resize_params| that were sent to the renderer bundled with the
+  // request to create a new RenderWidget.
+  void SetInitialRenderSizeParams(const ViewMsg_Resize_Params& resize_params);
 
   // Expose increment/decrement of the in-flight event count, so
   // RenderViewHostImpl can account for in-flight beforeunload/unload events.
@@ -702,9 +719,6 @@
   // most recent call to process_->WidgetRestored() / WidgetHidden().
   bool is_hidden_;
 
-  // Indicates whether a page is fullscreen or not.
-  bool is_fullscreen_;
-
   // Set if we are waiting for a repaint ack for the view.
   bool repaint_ack_pending_;
 
@@ -722,31 +736,21 @@
   // The current size of the RenderWidget.
   gfx::Size current_size_;
 
-  // The size of the view's backing surface in non-DPI-adjusted pixels.
-  gfx::Size physical_backing_size_;
-
-  // The amount that the viewport size given to Blink was shrunk by the URL-bar
-  // (always 0 on platforms where URL-bar hiding isn't supported).
-  float top_controls_layout_height_;
-
-  // The size of the visible viewport, which may be smaller than the view if the
-  // view is partially occluded (e.g. by a virtual keyboard).  The size is in
-  // DPI-adjusted pixels.
-  gfx::Size visible_viewport_size_;
-
-  // The size we last sent as requested size to the renderer. |current_size_|
-  // is only updated once the resize message has been ack'd. This on the other
-  // hand is updated when the resize message is sent. This is very similar to
-  // |resize_ack_pending_|, but the latter is not set if the new size has width
-  // or height zero, which is why we need this too.
-  gfx::Size last_requested_size_;
+  // Resize information that was previously sent to the renderer.
+  scoped_ptr<ViewMsg_Resize_Params> old_resize_params_;
 
   // The next auto resize to send.
   gfx::Size new_auto_size_;
 
   // True if the render widget host should track the render widget's size as
   // opposed to visa versa.
-  bool should_auto_resize_;
+  bool auto_resize_enabled_;
+
+  // The minimum size for the render widget if auto-resize is enabled.
+  gfx::Size min_size_for_auto_resize_;
+
+  // The maximum size for the render widget if auto-resize is enabled.
+  gfx::Size max_size_for_auto_resize_;
 
   bool waiting_for_screen_rects_ack_;
   gfx::Rect last_view_screen_rect_;
@@ -843,8 +847,6 @@
       base::Callback<void(const unsigned char*, size_t)> > PendingSnapshotMap;
   PendingSnapshotMap pending_browser_snapshots_;
 
-  cc::RollingTimeDeltaHistory browser_composite_latency_history_;
-
   base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostImpl);
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 830ab01..32ed9c8 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -139,9 +139,11 @@
   }
 
   // Allow poking at a few private members.
+  using RenderWidgetHostImpl::GetResizeParams;
   using RenderWidgetHostImpl::OnUpdateRect;
   using RenderWidgetHostImpl::RendererExited;
-  using RenderWidgetHostImpl::last_requested_size_;
+  using RenderWidgetHostImpl::SetInitialRenderSizeParams;
+  using RenderWidgetHostImpl::old_resize_params_;
   using RenderWidgetHostImpl::is_hidden_;
   using RenderWidgetHostImpl::resize_ack_pending_;
   using RenderWidgetHostImpl::input_router_;
@@ -440,10 +442,13 @@
     host_.reset(
         new MockRenderWidgetHost(delegate_.get(), process_, MSG_ROUTING_NONE));
     view_.reset(new TestView(host_.get()));
+    ConfigureView(view_.get());
     host_->SetView(view_.get());
+    SetInitialRenderSizeParams();
     host_->Init();
     host_->DisableGestureDebounce();
   }
+
   void TearDown() override {
     view_.reset();
     host_.reset();
@@ -464,6 +469,15 @@
     base::MessageLoop::current()->RunUntilIdle();
   }
 
+  void SetInitialRenderSizeParams() {
+    ViewMsg_Resize_Params render_size_params;
+    host_->GetResizeParams(&render_size_params);
+    host_->SetInitialRenderSizeParams(render_size_params);
+  }
+
+  virtual void ConfigureView(TestView* view) {
+  }
+
   int64 GetLatencyComponentId() {
     return host_->GetLatencyComponentId();
   }
@@ -630,7 +644,7 @@
   view_->SetMockPhysicalBackingSize(gfx::Size());
   host_->WasResized();
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(original_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Setting the bounds to a "real" rect should send out the notification.
@@ -639,7 +653,7 @@
   view_->ClearMockPhysicalBackingSize();
   host_->WasResized();
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(original_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Send out a update that's not a resize ack after setting resize ack pending
@@ -654,7 +668,7 @@
   process_->InitUpdateRectParams(&params);
   host_->OnUpdateRect(params);
   EXPECT_TRUE(host_->resize_ack_pending_);
-  EXPECT_EQ(second_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(second_size.size(), host_->old_resize_params_->new_size);
 
   // Sending out a new notification should NOT send out a new IPC message since
   // a resize ACK is pending.
@@ -663,7 +677,7 @@
   view_->set_bounds(third_size);
   host_->WasResized();
   EXPECT_TRUE(host_->resize_ack_pending_);
-  EXPECT_EQ(second_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(second_size.size(), host_->old_resize_params_->new_size);
   EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Send a update that's a resize ack, but for the original_size we sent. Since
@@ -674,7 +688,7 @@
   params.view_size = original_size.size();
   host_->OnUpdateRect(params);
   EXPECT_TRUE(host_->resize_ack_pending_);
-  EXPECT_EQ(third_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(third_size.size(), host_->old_resize_params_->new_size);
   ASSERT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Send the resize ack for the latest size.
@@ -682,7 +696,7 @@
   params.view_size = third_size.size();
   host_->OnUpdateRect(params);
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(third_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(third_size.size(), host_->old_resize_params_->new_size);
   ASSERT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
 
   // Now clearing the bounds should send out a notification but we shouldn't
@@ -692,7 +706,7 @@
   view_->set_bounds(gfx::Rect());
   host_->WasResized();
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(gfx::Size(), host_->last_requested_size_);
+  EXPECT_EQ(gfx::Size(), host_->old_resize_params_->new_size);
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Send a rect that has no area but has either width or height set.
@@ -700,21 +714,21 @@
   view_->set_bounds(gfx::Rect(0, 0, 0, 30));
   host_->WasResized();
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(gfx::Size(0, 30), host_->last_requested_size_);
+  EXPECT_EQ(gfx::Size(0, 30), host_->old_resize_params_->new_size);
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Set the same size again. It should not be sent again.
   process_->sink().ClearMessages();
   host_->WasResized();
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(gfx::Size(0, 30), host_->last_requested_size_);
+  EXPECT_EQ(gfx::Size(0, 30), host_->old_resize_params_->new_size);
   EXPECT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
 
   // A different size should be sent again, however.
   view_->set_bounds(gfx::Rect(0, 0, 0, 31));
   host_->WasResized();
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(gfx::Size(0, 31), host_->last_requested_size_);
+  EXPECT_EQ(gfx::Size(0, 31), host_->old_resize_params_->new_size);
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 }
 
@@ -729,7 +743,7 @@
   view_->set_bounds(original_size);
   host_->WasResized();
   EXPECT_TRUE(host_->resize_ack_pending_);
-  EXPECT_EQ(original_size.size(), host_->last_requested_size_);
+  EXPECT_EQ(original_size.size(), host_->old_resize_params_->new_size);
   EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
 
   // Simulate a renderer crash before the update message.  Ensure all the
@@ -738,7 +752,7 @@
   host_->SetView(NULL);
   host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
   EXPECT_FALSE(host_->resize_ack_pending_);
-  EXPECT_EQ(gfx::Size(), host_->last_requested_size_);
+  EXPECT_EQ(gfx::Size(), host_->old_resize_params_->new_size);
 
   // Reset the view so we can exit the test cleanly.
   host_->SetView(view_.get());
@@ -1494,4 +1508,39 @@
   ASSERT_FALSE(host_->input_router()->HasPendingEvents());
 }
 
+TEST_F(RenderWidgetHostTest, ResizeParams) {
+  gfx::Rect bounds(0, 0, 100, 100);
+  gfx::Size physical_backing_size(40, 50);
+  view_->set_bounds(bounds);
+  view_->SetMockPhysicalBackingSize(physical_backing_size);
+
+  ViewMsg_Resize_Params resize_params;
+  host_->GetResizeParams(&resize_params);
+  EXPECT_EQ(bounds.size(), resize_params.new_size);
+  EXPECT_EQ(physical_backing_size, resize_params.physical_backing_size);
+}
+
+class RenderWidgetHostInitialSizeTest : public RenderWidgetHostTest {
+ public:
+  RenderWidgetHostInitialSizeTest()
+      : RenderWidgetHostTest(), initial_size_(200, 100) {}
+
+  virtual void ConfigureView(TestView* view) override {
+    view->set_bounds(gfx::Rect(initial_size_));
+  }
+
+ protected:
+  gfx::Size initial_size_;
+};
+
+TEST_F(RenderWidgetHostInitialSizeTest, InitialSize) {
+  // Having an initial size set means that the size information had been sent
+  // with the reqiest to new up the RenderView and so subsequent WasResized
+  // calls should not result in new IPC (unless the size has actually changed).
+  host_->WasResized();
+  EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
+  EXPECT_EQ(initial_size_, host_->old_resize_params_->new_size);
+  EXPECT_TRUE(host_->resize_ack_pending_);
+}
+
 }  // namespace content
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 e8a4f55..8c5b214 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -279,9 +279,7 @@
       gesture_provider_(CreateGestureProviderConfig(), this),
       gesture_text_selector_(this),
       accelerated_surface_route_id_(0),
-      using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
-                                        widget_host->GetProcess()->GetID(),
-                                        widget_host->GetRoutingID()) != NULL),
+      using_browser_compositor_(CompositorImpl::IsInitialized()),
       frame_evictor_(new DelegatedFrameEvictor(this)),
       locks_on_frame_count_(0),
       observing_root_window_(false),
@@ -670,7 +668,7 @@
 }
 
 void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
-  DCHECK(!using_synchronous_compositor_);
+  DCHECK(using_browser_compositor_);
   TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
                "enabled", enabled);
   if (enabled)
@@ -841,7 +839,7 @@
     return;
   }
   base::TimeTicks start_time = base::TimeTicks::Now();
-  if (!using_synchronous_compositor_ && !IsSurfaceAvailableForCopy()) {
+  if (using_browser_compositor_ && !IsSurfaceAvailableForCopy()) {
     callback.Run(false, SkBitmap());
     return;
   }
@@ -853,7 +851,7 @@
   gfx::Rect src_subrect_in_pixel =
       ConvertRectToPixel(device_scale_factor, src_subrect);
 
-  if (using_synchronous_compositor_) {
+  if (!using_browser_compositor_) {
     SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
                             color_type);
     UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
@@ -1143,12 +1141,12 @@
 bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
   // The synchronous (WebView) compositor does not have a proper browser
   // compositor with which to drive animations.
-  return !using_synchronous_compositor_;
+  return using_browser_compositor_;
 }
 
 void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
   DCHECK(content_view_core_);
-  DCHECK(!using_synchronous_compositor_);
+  DCHECK(using_browser_compositor_);
   content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
 }
 
@@ -1178,7 +1176,7 @@
 
 scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
   DCHECK(content_view_core_);
-  if (using_synchronous_compositor_)
+  if (!using_browser_compositor_)
     return content_view_core_->CreatePopupTouchHandleDrawable();
 
   return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
@@ -1285,7 +1283,7 @@
 
 void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
   // The synchronous compositor does not requre BeginFrame messages.
-  if (using_synchronous_compositor_)
+  if (!using_browser_compositor_)
     requests &= FLUSH_INPUT;
 
   bool should_request_vsync = !outstanding_vsync_requests_ && requests;
@@ -1330,8 +1328,12 @@
                "frame_time_us", frame_time.ToInternalValue());
   base::TimeTicks display_time = frame_time + vsync_period;
 
-  base::TimeTicks deadline =
-      display_time - host_->GetEstimatedBrowserCompositeTime();
+  // TODO(brianderson): Use adaptive draw-time estimation.
+  base::TimeDelta estimated_browser_composite_time =
+      base::TimeDelta::FromMicroseconds(
+          (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
+
+  base::TimeTicks deadline = display_time - estimated_browser_composite_time;
 
   host_->Send(new ViewMsg_BeginFrame(
       host_->GetRoutingID(),
@@ -1375,7 +1377,7 @@
 gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
   gfx::GLSurfaceHandle handle =
       gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
-  if (CompositorImpl::IsInitialized()) {
+  if (using_browser_compositor_) {
     handle.parent_client_id =
         ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
   }
@@ -1645,7 +1647,7 @@
 
 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
   DCHECK(content_view_core_);
-  DCHECK(!using_synchronous_compositor_);
+  DCHECK(using_browser_compositor_);
   RunAckCallbacks();
   overscroll_effect_.reset();
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 129b773..97b2ba4 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -396,7 +396,7 @@
   // Size to use if we have no backing ContentViewCore
   gfx::Size default_size_;
 
-  const bool using_synchronous_compositor_;
+  const bool using_browser_compositor_;
 
   scoped_ptr<DelegatedFrameEvictor> frame_evictor_;
 
diff --git a/content/browser/ssl/ssl_client_auth_handler.cc b/content/browser/ssl/ssl_client_auth_handler.cc
index 8cab2c7..72231f4 100644
--- a/content/browser/ssl/ssl_client_auth_handler.cc
+++ b/content/browser/ssl/ssl_client_auth_handler.cc
@@ -5,84 +5,77 @@
 #include "content/browser/ssl/ssl_client_auth_handler.h"
 
 #include "base/bind.h"
-#include "base/logging.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "net/cert/x509_certificate.h"
+#include "net/http/http_transaction_factory.h"
 #include "net/ssl/client_cert_store.h"
 #include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
 
 namespace content {
 
-namespace {
-
-typedef base::Callback<void(net::X509Certificate*)> CertificateCallback;
-
-void CertificateSelectedOnUIThread(
-    const CertificateCallback& io_thread_callback,
-    net::X509Certificate* cert) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(io_thread_callback, make_scoped_refptr(cert)));
-}
-
-void SelectCertificateOnUIThread(
-    int render_process_host_id,
-    int render_frame_host_id,
-    net::SSLCertRequestInfo* cert_request_info,
-    const CertificateCallback& io_thread_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  GetContentClient()->browser()->SelectClientCertificate(
-      render_process_host_id, render_frame_host_id, cert_request_info,
-      base::Bind(&CertificateSelectedOnUIThread, io_thread_callback));
-}
-
-}  // namespace
-
 SSLClientAuthHandler::SSLClientAuthHandler(
     scoped_ptr<net::ClientCertStore> client_cert_store,
     net::URLRequest* request,
-    net::SSLCertRequestInfo* cert_request_info,
-    const SSLClientAuthHandler::CertificateCallback& callback)
+    net::SSLCertRequestInfo* cert_request_info)
     : request_(request),
+      http_network_session_(
+          request_->context()->http_transaction_factory()->GetSession()),
       cert_request_info_(cert_request_info),
-      client_cert_store_(client_cert_store.Pass()),
-      callback_(callback),
-      weak_factory_(this) {
+      client_cert_store_(client_cert_store.Pass()) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 }
 
 SSLClientAuthHandler::~SSLClientAuthHandler() {
+  // If we were simply dropped, then act as if we selected no certificate.
+  DoCertificateSelected(NULL);
+}
+
+void SSLClientAuthHandler::OnRequestCancelled() {
+  request_ = NULL;
 }
 
 void SSLClientAuthHandler::SelectCertificate() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK(request_);
 
   if (client_cert_store_) {
     client_cert_store_->GetClientCerts(
         *cert_request_info_,
         &cert_request_info_->client_certs,
-        base::Bind(&SSLClientAuthHandler::DidGetClientCerts,
-                   weak_factory_.GetWeakPtr()));
+        base::Bind(&SSLClientAuthHandler::DidGetClientCerts, this));
   } else {
     DidGetClientCerts();
   }
 }
 
+void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  DVLOG(1) << this << " CertificateSelected " << cert;
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(
+          &SSLClientAuthHandler::DoCertificateSelected, this,
+          make_scoped_refptr(cert)));
+}
+
 void SSLClientAuthHandler::DidGetClientCerts() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  // Request may have cancelled while we were getting client certs.
+  if (!request_)
+    return;
 
   // Note that if |client_cert_store_| is NULL, we intentionally fall through to
   // DoCertificateSelected. This is for platforms where the client cert matching
-  // is not performed by Chrome. Those platforms handle the cert matching before
-  // showing the dialog.
+  // is not performed by Chrome, the platform can handle the cert matching
+  // before showing the dialog.
   if (client_cert_store_ && cert_request_info_->client_certs.empty()) {
     // No need to query the user if there are no certs to choose from.
-    CertificateSelected(NULL);
+    DoCertificateSelected(NULL);
     return;
   }
 
@@ -90,27 +83,43 @@
   int render_frame_host_id;
   if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame(
           &render_process_host_id,
-          &render_frame_host_id)) {
+          &render_frame_host_id))
     NOTREACHED();
-    CertificateSelected(NULL);
-    return;
-  }
 
+  // If the RVH does not exist by the time this task gets run, then the task
+  // will be dropped and the scoped_refptr to SSLClientAuthHandler will go
+  // away, so we do not leak anything. The destructor takes care of ensuring
+  // the net::URLRequest always gets a response.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&SelectCertificateOnUIThread,
-                 render_process_host_id, render_frame_host_id,
-                 cert_request_info_,
-                 base::Bind(&SSLClientAuthHandler::CertificateSelected,
-                            weak_factory_.GetWeakPtr())));
+      base::Bind(
+          &SSLClientAuthHandler::DoSelectCertificate, this,
+          render_process_host_id, render_frame_host_id));
 }
 
-void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
+void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) {
   VLOG(1) << this << " DoCertificateSelected " << cert;
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  // request_ could have been NULLed if the request was cancelled while the
+  // user was choosing a cert, or because we have already responded to the
+  // certificate.
+  if (request_) {
+    request_->ContinueWithCertificate(cert);
 
-  callback_.Run(cert);
-  // |this| may be deleted at this point.
+    ResourceDispatcherHostImpl::Get()->
+        ClearSSLClientAuthHandlerForRequest(request_);
+    request_ = NULL;
+  }
+}
+
+void SSLClientAuthHandler::DoSelectCertificate(
+    int render_process_host_id, int render_frame_host_id) {
+  GetContentClient()->browser()->SelectClientCertificate(
+      render_process_host_id,
+      render_frame_host_id,
+      http_network_session_,
+      cert_request_info_.get(),
+      base::Bind(&SSLClientAuthHandler::CertificateSelected, this));
 }
 
 }  // namespace content
diff --git a/content/browser/ssl/ssl_client_auth_handler.h b/content/browser/ssl/ssl_client_auth_handler.h
index f95e65d..b848d54 100644
--- a/content/browser/ssl/ssl_client_auth_handler.h
+++ b/content/browser/ssl/ssl_client_auth_handler.h
@@ -6,57 +6,79 @@
 #define CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_HANDLER_H_
 
 #include "base/basictypes.h"
-#include "base/callback.h"
 #include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner_helpers.h"
+#include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/ssl/ssl_cert_request_info.h"
 
 namespace net {
 class ClientCertStore;
+class HttpNetworkSession;
 class URLRequest;
 class X509Certificate;
 }  // namespace net
 
 namespace content {
 
-// This class handles the approval and selection of a certificate for SSL client
-// authentication by the user. Should only be used on the IO thread. If the
-// SSLClientAuthHandler is destroyed before the certificate is selected, the
-// selection is canceled and the callback never called.
-class SSLClientAuthHandler {
- public:
-  typedef base::Callback<void(net::X509Certificate*)> CertificateCallback;
+class ResourceContext;
 
+// This class handles the approval and selection of a certificate for SSL client
+// authentication by the user.
+// It is self-owned and deletes itself when the UI reports the user selection or
+// when the net::URLRequest is cancelled.
+class CONTENT_EXPORT SSLClientAuthHandler
+    : public base::RefCountedThreadSafe<
+          SSLClientAuthHandler, BrowserThread::DeleteOnIOThread> {
+ public:
   SSLClientAuthHandler(scoped_ptr<net::ClientCertStore> client_cert_store,
                        net::URLRequest* request,
-                       net::SSLCertRequestInfo* cert_request_info,
-                       const CertificateCallback& callback);
-  ~SSLClientAuthHandler();
+                       net::SSLCertRequestInfo* cert_request_info);
 
   // Selects a certificate and resumes the URL request with that certificate.
+  // Should only be called on the IO thread.
   void SelectCertificate();
 
+  // Invoked when the request associated with this handler is cancelled.
+  // Should only be called on the IO thread.
+  void OnRequestCancelled();
+
+  // Calls DoCertificateSelected on the I/O thread.
+  // Called on the UI thread after the user has made a selection (which may
+  // be long after DoSelectCertificate returns, if the UI is modeless/async.)
+  void CertificateSelected(net::X509Certificate* cert);
+
+ protected:
+  virtual ~SSLClientAuthHandler();
+
  private:
+  friend class base::RefCountedThreadSafe<
+      SSLClientAuthHandler, BrowserThread::DeleteOnIOThread>;
+  friend class BrowserThread;
+  friend class base::DeleteHelper<SSLClientAuthHandler>;
+
   // Called when ClientCertStore is done retrieving the cert list.
   void DidGetClientCerts();
 
-  // Called when the user has selected a cert.
-  void CertificateSelected(net::X509Certificate* cert);
+  // Notifies that the user has selected a cert.
+  // Called on the IO thread.
+  void DoCertificateSelected(net::X509Certificate* cert);
+
+  // Selects a client certificate on the UI thread.
+  void DoSelectCertificate(int render_process_host_id,
+                           int render_frame_host_id);
 
   // The net::URLRequest that triggered this client auth.
   net::URLRequest* request_;
 
+  // The HttpNetworkSession |request_| is associated with.
+  const net::HttpNetworkSession* http_network_session_;
+
   // The certs to choose from.
   scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
 
   scoped_ptr<net::ClientCertStore> client_cert_store_;
 
-  // The callback to call when the certificate is selected.
-  CertificateCallback callback_;
-
-  base::WeakPtrFactory<SSLClientAuthHandler> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(SSLClientAuthHandler);
 };
 
diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc
index c084772..4ca2157 100644
--- a/content/common/gpu/image_transport_surface.cc
+++ b/content/common/gpu/image_transport_surface.cc
@@ -223,10 +223,6 @@
   // GetVsyncValues before SwapBuffers to work around Mali driver bug:
   // crbug.com/223558.
   SendVSyncUpdateIfAvailable();
-  for (size_t i = 0; i < latency_info_.size(); ++i) {
-    latency_info_[i].AddLatencyNumber(
-        ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0);
-  }
   bool result = gfx::GLSurfaceAdapter::SwapBuffers();
   for (size_t i = 0; i < latency_info_.size(); i++) {
     latency_info_[i].AddLatencyNumber(
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
index 2f71b82..df8ec5b 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -377,12 +377,12 @@
       texture_manager->SetLevelInfo(texture_ref,
                                     texture_target_,
                                     0,
-                                    0,
+                                    GL_RGBA,
                                     texture_dimensions_.width(),
                                     texture_dimensions_.height(),
                                     1,
                                     0,
-                                    0,
+                                    GL_RGBA,
                                     0,
                                     false);
     } else {
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 426ac1f..bb55e85 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -413,6 +413,26 @@
   IPC_STRUCT_MEMBER(int, flags)
 IPC_STRUCT_END()
 
+IPC_STRUCT_BEGIN(ViewMsg_Resize_Params)
+  // Information about the screen (dpi, depth, etc..).
+  IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
+  // The size of the renderer.
+  IPC_STRUCT_MEMBER(gfx::Size, new_size)
+  // The size of the view's backing surface in non-DPI-adjusted pixels.
+  IPC_STRUCT_MEMBER(gfx::Size, physical_backing_size)
+  // The amount that the viewport size given to Blink was shrunk by the URL-bar
+  // (always 0 on platforms where URL-bar hiding isn't supported).
+  IPC_STRUCT_MEMBER(float, top_controls_layout_height)
+  // The size of the visible viewport, which may be smaller than the view if the
+  // view is partially occluded (e.g. by a virtual keyboard).  The size is in
+  // DPI-adjusted pixels.
+  IPC_STRUCT_MEMBER(gfx::Size, visible_viewport_size)
+  // The resizer rect.
+  IPC_STRUCT_MEMBER(gfx::Rect, resizer_rect)
+  // Indicates whether a page is fullscreen or not.
+  IPC_STRUCT_MEMBER(bool, is_fullscreen)
+IPC_STRUCT_END()
+
 IPC_STRUCT_BEGIN(ViewMsg_New_Params)
   // Renderer-wide preferences.
   IPC_STRUCT_MEMBER(content::RendererPreferences, renderer_preferences)
@@ -460,8 +480,17 @@
   // to a view and are only updated by the renderer after this initial value.
   IPC_STRUCT_MEMBER(int32, next_page_id)
 
-  // The properties of the screen associated with the view.
-  IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
+  // The initial renderer size.
+  IPC_STRUCT_MEMBER(ViewMsg_Resize_Params, initial_size)
+
+  // Whether to enable auto-resize.
+  IPC_STRUCT_MEMBER(bool, enable_auto_resize)
+
+  // The minimum size to layout the page if auto-resize is enabled.
+  IPC_STRUCT_MEMBER(gfx::Size, min_size)
+
+  // The maximum size to layout the page if auto-resize is enabled.
+  IPC_STRUCT_MEMBER(gfx::Size, max_size)
 IPC_STRUCT_END()
 
 IPC_STRUCT_BEGIN(ViewMsg_PostMessage_Params)
@@ -564,16 +593,6 @@
 // Expects a Close_ACK message when finished.
 IPC_MESSAGE_ROUTED0(ViewMsg_Close)
 
-IPC_STRUCT_BEGIN(ViewMsg_Resize_Params)
-  IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
-  IPC_STRUCT_MEMBER(gfx::Size, new_size)
-  IPC_STRUCT_MEMBER(gfx::Size, physical_backing_size)
-  IPC_STRUCT_MEMBER(float, top_controls_layout_height)
-  IPC_STRUCT_MEMBER(gfx::Size, visible_viewport_size)
-  IPC_STRUCT_MEMBER(gfx::Rect, resizer_rect)
-  IPC_STRUCT_MEMBER(bool, is_fullscreen)
-IPC_STRUCT_END()
-
 // Tells the render view to change its size.  A ViewHostMsg_UpdateRect message
 // is generated in response provided new_size is not empty and not equal to
 // the view's current size.  The generated ViewHostMsg_UpdateRect message will
diff --git a/content/public/android/java/res/menu/select_action_menu.xml b/content/public/android/java/res/menu/select_action_menu.xml
index 65c729a..3793260 100644
--- a/content/public/android/java/res/menu/select_action_menu.xml
+++ b/content/public/android/java/res/menu/select_action_menu.xml
@@ -37,14 +37,14 @@
         />
     <item
         android:id="@+id/select_action_menu_share"
-        android:icon="@drawable/ic_menu_share_holo_light"
         android:title="@string/actionbar_share"
         android:showAsAction="always|withText"
+        style="@style/SelectActionMenuShare"
         />
     <item
         android:id="@+id/select_action_menu_web_search"
-        android:icon="@drawable/ic_menu_search_holo_light"
         android:title="@string/actionbar_web_search"
         android:showAsAction="always|withText"
+        style="@style/SelectActionMenuWebSearch"
         />
 </menu>
diff --git a/content/public/android/java/res/values-v17/styles.xml b/content/public/android/java/res/values-v17/styles.xml
index 7c439dc..dbdc8b1 100644
--- a/content/public/android/java/res/values-v17/styles.xml
+++ b/content/public/android/java/res/values-v17/styles.xml
@@ -10,4 +10,10 @@
         <item name="select_dialog_singlechoice">@android:layout/select_dialog_singlechoice</item>
         <item name="select_dialog_multichoice">@android:layout/select_dialog_multichoice</item>
     </style>
+    <style name="SelectActionMenuShare">
+        <item name="android:icon">@drawable/ic_menu_share_holo_light</item>
+    </style>
+    <style name="SelectActionMenuWebSearch">
+        <item name="android:icon">@drawable/ic_menu_search_holo_light</item>
+    </style>
 </resources>
diff --git a/content/public/android/java/res/values-v21/styles.xml b/content/public/android/java/res/values-v21/styles.xml
new file mode 100644
index 0000000..a01b0c7
--- /dev/null
+++ b/content/public/android/java/res/values-v21/styles.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <style name="SelectActionMenuShare">
+        <item name="android:icon">?android:attr/actionModeShareDrawable</item>
+    </style>
+    <style name="SelectActionMenuWebSearch">
+        <item name="android:icon">?android:attr/actionModeWebSearchDrawable</item>
+    </style>
+</resources>
+
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java b/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java
index 4043988..b2d6e0a 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java
@@ -4,10 +4,8 @@
 
 package org.chromium.content.browser;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.Context;
-import android.content.ContextWrapper;
 import android.content.DialogInterface;
 import android.graphics.Point;
 import android.provider.Settings;
@@ -231,7 +229,7 @@
 
         mCurrentState = STATE_ERROR;
 
-        if (!isActivityContext(getContext())) {
+        if (ContentViewCore.activityFromContext(getContext()) == null) {
             Log.w(TAG, "Unable to show alert dialog because it requires an activity context");
             return;
         }
@@ -424,16 +422,6 @@
         return videoView;
     }
 
-    private static boolean isActivityContext(Context context) {
-        // Only retrieve the base context if the supplied context is a ContextWrapper but not
-        // an Activity, given that Activity is already a subclass of ContextWrapper.
-        if (context instanceof ContextWrapper && !(context instanceof Activity)) {
-            context = ((ContextWrapper) context).getBaseContext();
-            return isActivityContext(context);
-        }
-        return context instanceof Activity;
-    }
-
     public void removeSurfaceView() {
         removeView(mVideoSurfaceView);
         removeView(mProgressView);
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 8e4645f..b5bdeaa 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
@@ -10,6 +10,7 @@
 import android.content.ClipboardManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
@@ -358,6 +359,22 @@
         public void onSmartClipDataExtracted(String text, String html, Rect clipRect);
     }
 
+    /**
+     * Cast from Context to Activity taking ContextWrapper into account.
+     */
+    public static Activity activityFromContext(Context context) {
+        // Only retrieve the base context if the supplied context is a ContextWrapper but not
+        // an Activity, given that Activity is already a subclass of ContextWrapper.
+        if (context instanceof Activity) {
+            return ((Activity) context);
+        } else if (context instanceof ContextWrapper) {
+            context = ((ContextWrapper) context).getBaseContext();
+            return activityFromContext(context);
+        } else {
+            return null;
+        }
+    }
+
     private final Context mContext;
     private ViewGroup mContainerView;
     private InternalAccessDelegate mContainerViewInternals;
@@ -1930,7 +1947,7 @@
                     i.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
                     i.putExtra(SearchManager.QUERY, query);
                     i.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName());
-                    if (!(getContext() instanceof Activity)) {
+                    if (activityFromContext(getContext()) == null) {
                         i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                     }
                     try {
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java b/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java
index 3035251..25459fb 100644
--- a/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java
+++ b/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java
@@ -121,6 +121,7 @@
 
     private void createActionMenu(ActionMode mode, Menu menu) {
         mode.getMenuInflater().inflate(R.menu.select_action_menu, menu);
+
         if (!mEditable || !canPaste()) {
             menu.removeItem(R.id.select_action_menu_paste);
         }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
index 6745a40..ddc655b 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
@@ -4,10 +4,15 @@
 
 package org.chromium.content.browser;
 
+import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
+
 import android.test.suitebuilder.annotation.SmallTest;
 
+import junit.framework.Assert;
+
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
+import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_shell_apk.ContentShellActivity;
 
 import java.lang.annotation.Annotation;
@@ -16,6 +21,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.lang.ref.WeakReference;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * Part of the test suite for the Java Bridge. Tests a number of features including ...
@@ -172,15 +178,27 @@
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
     public void testRemovalNotReflectedUntilReload() throws Throwable {
-        injectObjectAndReload(new Object(), "testObject");
+        injectObjectAndReload(new Object() {
+            public void method() {
+                mTestController.setStringValue("I'm here");
+            }
+        }, "testObject");
         assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+        executeJavaScript("testObject.method()");
+        assertEquals("I'm here", mTestController.waitForStringValue());
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
                 getContentViewCore().removeJavascriptInterface("testObject");
             }
         });
+        // Check that the Java object is being held by the Java bridge, thus it's not
+        // collected. Note that despite that what JavaDoc says about invoking "gc()", both Dalvik
+        // and ART actually run the collector if called via Runtime.
+        Runtime.getRuntime().gc();
         assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+        executeJavaScript("testObject.method()");
+        assertEquals("I'm here", mTestController.waitForStringValue());
         synchronousPageReload();
         assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
     }
@@ -521,6 +539,47 @@
 
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
+    public void testBlockingUiThreadDoesNotBlockCallsFromJs() throws Throwable {
+        class TestObject {
+            private CountDownLatch mLatch;
+            public TestObject() {
+                mLatch = new CountDownLatch(1);
+            }
+            public boolean waitOnTheLatch() throws Exception {
+                return mLatch.await(scaleTimeout(10000),
+                        java.util.concurrent.TimeUnit.MILLISECONDS);
+            }
+            public void unlockTheLatch() throws Exception {
+                mTestController.setStringValue("unlocked");
+                mLatch.countDown();
+            }
+        }
+        final TestObject testObject = new TestObject();
+        injectObjectAndReload(testObject, "testObject");
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // loadUrl is asynchronous, the JS code will start running on the renderer
+                // thread. As soon as we exit loadUrl, the browser UI thread will be stuck waiting
+                // on the latch. If blocking the browser thread blocks Java Bridge, then the call
+                // to "unlockTheLatch()" will be executed after the waiting timeout, thus the
+                // string value will not yet be updated by the injected object.
+                mTestController.setStringValue("locked");
+                getWebContents().getNavigationController().loadUrl(new LoadUrlParams(
+                        "javascript:(function() { testObject.unlockTheLatch() })()"));
+                try {
+                    assertTrue(testObject.waitOnTheLatch());
+                } catch (Exception e) {
+                    android.util.Log.e("JavaBridgeBasicsTest", "Wait exception", e);
+                    Assert.fail("Wait exception");
+                }
+                assertEquals("unlocked", mTestController.getStringValue());
+            }
+        });
+    }
+
+    @SmallTest
+    @Feature({"AndroidWebView", "Android-JavaBridge"})
     public void testPublicInheritedMethod() throws Throwable {
         class Base {
             public void method(int x) {
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 728d822..cce349c 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -176,14 +176,6 @@
   return NULL;
 }
 
-void ContentBrowserClient::SelectClientCertificate(
-    int render_process_id,
-    int render_frame_id,
-    net::SSLCertRequestInfo* cert_request_info,
-    const base::Callback<void(net::X509Certificate*)>& callback) {
-  callback.Run(NULL);
-}
-
 net::URLRequestContext* ContentBrowserClient::OverrideRequestContextForURL(
     const GURL& url, ResourceContext* context) {
   return NULL;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 5a27d98..b009696 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -58,6 +58,7 @@
 namespace net {
 class CookieOptions;
 class CookieStore;
+class HttpNetworkSession;
 class NetLog;
 class SSLCertRequestInfo;
 class SSLInfo;
@@ -401,8 +402,9 @@
   virtual void SelectClientCertificate(
       int render_process_id,
       int render_frame_id,
+      const net::HttpNetworkSession* network_session,
       net::SSLCertRequestInfo* cert_request_info,
-      const base::Callback<void(net::X509Certificate*)>& callback);
+      const base::Callback<void(net::X509Certificate*)>& callback) {}
 
   // Adds a new installable certificate or private key.
   // Typically used to install an X.509 user certificate.
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 03c7578..c6e9a4d 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -494,8 +494,8 @@
 // pinch gestures.
 const char kEnableViewport[]                = "enable-viewport";
 
-// Enables the use of the legacy viewport meta tag. Turning this on also
-// turns on the @viewport CSS rule
+// Enables the viewport meta tag, the de facto way to control layout which works
+// only on mobile browsers.
 const char kEnableViewportMeta[]            = "enable-viewport-meta";
 
 // Resizes of the main frame are the caused by changing between landscape
diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc
index 9b11678..35226ff 100644
--- a/content/public/test/content_test_suite_base.cc
+++ b/content/public/test/content_test_suite_base.cc
@@ -29,6 +29,7 @@
 #include "base/android/jni_android.h"
 #include "content/browser/android/browser_jni_registrar.h"
 #include "content/common/android/common_jni_registrar.h"
+#include "content/public/browser/android/compositor.h"
 #include "media/base/android/media_jni_registrar.h"
 #include "net/android/net_jni_registrar.h"
 #include "ui/base/android/ui_base_jni_registrar.h"
@@ -80,6 +81,8 @@
   net::android::RegisterJni(env);
   ui::android::RegisterJni(env);
   ui::shell_dialogs::RegisterJni(env);
+
+  content::Compositor::Initialize();
 #endif
 
   testing::UnitTest::GetInstance()->listeners().Append(
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 5a86b05..f931461 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -204,7 +204,11 @@
                              false,  // hidden
                              false,  // never_visible
                              1,      // next_page_id
-                             blink::WebScreenInfo());
+                             *InitialSizeParams(),
+                             false, // enable_auto_resize
+                             gfx::Size(), // min_size
+                             gfx::Size() // max_size
+                            );
   view->AddRef();
   view_ = view;
 }
@@ -407,6 +411,10 @@
   return new ContentRendererClient;
 }
 
+scoped_ptr<ViewMsg_Resize_Params> RenderViewTest::InitialSizeParams() {
+  return make_scoped_ptr(new ViewMsg_Resize_Params());
+}
+
 void RenderViewTest::GoToOffset(int offset, const PageState& state) {
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
 
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h
index baab05a..46dc35c 100644
--- a/content/public/test/render_view_test.h
+++ b/content/public/test/render_view_test.h
@@ -19,6 +19,8 @@
 #include "third_party/WebKit/public/platform/Platform.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 
+struct ViewMsg_Resize_Params;
+
 namespace blink {
 class WebWidget;
 }
@@ -133,6 +135,9 @@
   virtual ContentBrowserClient* CreateContentBrowserClient();
   virtual ContentRendererClient* CreateContentRendererClient();
 
+  // Allows a subclass to customize the initial size of the RenderView.
+  virtual scoped_ptr<ViewMsg_Resize_Params> InitialSizeParams();
+
   // testing::Test
   void SetUp() override;
 
diff --git a/content/renderer/media/rtc_data_channel_handler.cc b/content/renderer/media/rtc_data_channel_handler.cc
index 084a020..e37adf3 100644
--- a/content/renderer/media/rtc_data_channel_handler.cc
+++ b/content/renderer/media/rtc_data_channel_handler.cc
@@ -50,7 +50,10 @@
   channel_->RegisterObserver(this);
 }
 
-RtcDataChannelHandler::Observer::~Observer() {}
+RtcDataChannelHandler::Observer::~Observer() {
+  DVLOG(3) << "dtor";
+  DCHECK(!channel_.get()) << "Unregister hasn't been called.";
+}
 
 const scoped_refptr<base::SingleThreadTaskRunner>&
 RtcDataChannelHandler::Observer::main_thread() const {
@@ -59,12 +62,19 @@
 
 const scoped_refptr<webrtc::DataChannelInterface>&
 RtcDataChannelHandler::Observer::channel() const {
+  DCHECK(main_thread_->BelongsToCurrentThread());
   return channel_;
 }
 
-void RtcDataChannelHandler::Observer::ClearHandler() {
+void RtcDataChannelHandler::Observer::Unregister() {
   DCHECK(main_thread_->BelongsToCurrentThread());
   handler_ = nullptr;
+  if (channel_.get()) {
+    channel_->UnregisterObserver();
+    // Now that we're guaranteed to not get further OnStateChange callbacks,
+    // it's safe to release our reference to the channel.
+    channel_ = nullptr;
+  }
 }
 
 void RtcDataChannelHandler::Observer::OnStateChange() {
@@ -127,13 +137,18 @@
 RtcDataChannelHandler::~RtcDataChannelHandler() {
   DCHECK(thread_checker_.CalledOnValidThread());
   DVLOG(1) << "::dtor";
-  observer_->ClearHandler();
+  DCHECK(!observer_.get());
 }
 
 void RtcDataChannelHandler::setClient(
     blink::WebRTCDataChannelHandlerClient* client) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  DVLOG(3) << "setClient " << client;
   webkit_client_ = client;
+  if (!client) {
+    observer_->Unregister();
+    observer_ = nullptr;
+  }
 }
 
 blink::WebString RtcDataChannelHandler::label() {
@@ -273,6 +288,7 @@
 }
 
 void RtcDataChannelHandler::RecordMessageSent(size_t num_bytes) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   // Currently, messages are capped at some fairly low limit (16 Kb?)
   // but we may allow unlimited-size messages at some point, so making
   // the histogram maximum quite large (100 Mb) to have some
diff --git a/content/renderer/media/rtc_data_channel_handler.h b/content/renderer/media/rtc_data_channel_handler.h
index 79addde..efcec2d 100644
--- a/content/renderer/media/rtc_data_channel_handler.h
+++ b/content/renderer/media/rtc_data_channel_handler.h
@@ -74,7 +74,10 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& main_thread() const;
     const scoped_refptr<webrtc::DataChannelInterface>& channel() const;
 
-    void ClearHandler();
+    // Clears the internal |handler_| pointer so that no further callbacks
+    // will be attempted, disassociates this observer from the channel and
+    // releases the channel pointer. Must be called on the main thread.
+    void Unregister();
 
    private:
     friend class base::RefCountedThreadSafe<RtcDataChannelHandler::Observer>;
@@ -89,7 +92,7 @@
 
     RtcDataChannelHandler* handler_;
     const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
-    const scoped_refptr<webrtc::DataChannelInterface> channel_;
+    scoped_refptr<webrtc::DataChannelInterface> channel_;
   };
 
   scoped_refptr<Observer> observer_;
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index 2ee286a..3bcda49 100644
--- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -966,6 +966,7 @@
       pc_handler_->createDataChannel("d1", blink::WebRTCDataChannelInit()));
   EXPECT_TRUE(channel.get() != NULL);
   EXPECT_EQ(label, channel->label());
+  channel->setClient(nullptr);
 }
 
 TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) {
diff --git a/content/renderer/media/webrtc/media_stream_track_metrics.cc b/content/renderer/media/webrtc/media_stream_track_metrics.cc
index d4ce6b4..d6962c3 100644
--- a/content/renderer/media/webrtc/media_stream_track_metrics.cc
+++ b/content/renderer/media/webrtc/media_stream_track_metrics.cc
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/md5.h"
+#include "base/thread_task_runner_handle.h"
 #include "content/common/media/media_stream_track_metrics_host_messages.h"
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -20,37 +21,102 @@
 using webrtc::VideoTrackVector;
 
 namespace content {
+namespace {
+typedef std::set<std::string> IdSet;
 
-class MediaStreamTrackMetricsObserver : public webrtc::ObserverInterface {
+template <class T>
+IdSet GetTrackIds(const std::vector<rtc::scoped_refptr<T>>& tracks) {
+  IdSet track_ids;
+  for (const auto& track : tracks)
+    track_ids.insert(track->id());
+  return track_ids;
+}
+
+// TODO(tommi): Consolidate this and TrackObserver since these implementations
+// are fundamentally achieving the same thing (aside from specific logic inside
+// the OnChanged callbacks).
+class MediaStreamObserver
+    : public base::RefCountedThreadSafe<MediaStreamObserver>,
+      public webrtc::ObserverInterface {
+ public:
+  typedef base::Callback<
+      void(const IdSet& audio_track_ids, const IdSet& video_track_ids)>
+          OnChangedCallback;
+
+  MediaStreamObserver(
+      const OnChangedCallback& callback,
+      const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+      webrtc::MediaStreamInterface* stream)
+      : main_thread_(main_thread), stream_(stream), callback_(callback) {
+    signaling_thread_.DetachFromThread();
+    stream_->RegisterObserver(this);
+  }
+
+  const scoped_refptr<webrtc::MediaStreamInterface>& stream() const {
+    DCHECK(main_thread_->BelongsToCurrentThread());
+    return stream_;
+  }
+
+  void Unregister() {
+    DCHECK(main_thread_->BelongsToCurrentThread());
+    callback_.Reset();
+    stream_->UnregisterObserver(this);
+    stream_ = nullptr;
+  }
+
+ private:
+  friend class base::RefCountedThreadSafe<MediaStreamObserver>;
+  ~MediaStreamObserver() override {
+    DCHECK(!stream_.get()) << "must have been unregistered before deleting";
+  }
+
+  // webrtc::ObserverInterface implementation.
+  void OnChanged() override {
+    DCHECK(signaling_thread_.CalledOnValidThread());
+    main_thread_->PostTask(FROM_HERE,
+        base::Bind(&MediaStreamObserver::OnChangedOnMainThread, this,
+                   GetTrackIds(stream_->GetAudioTracks()),
+                   GetTrackIds(stream_->GetVideoTracks())));
+  }
+
+  void OnChangedOnMainThread(const IdSet& audio_track_ids,
+                             const IdSet& video_track_ids) {
+    DCHECK(main_thread_->BelongsToCurrentThread());
+    if (!callback_.is_null())
+      callback_.Run(audio_track_ids, video_track_ids);
+  }
+
+  const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+  scoped_refptr<webrtc::MediaStreamInterface> stream_;
+  OnChangedCallback callback_;  // Only touched on the main thread.
+  base::ThreadChecker signaling_thread_;
+};
+
+}  // namespace
+
+class MediaStreamTrackMetricsObserver {
  public:
   MediaStreamTrackMetricsObserver(
       MediaStreamTrackMetrics::StreamType stream_type,
       MediaStreamInterface* stream,
       MediaStreamTrackMetrics* owner);
-  ~MediaStreamTrackMetricsObserver() override;
+  ~MediaStreamTrackMetricsObserver();
 
   // Sends begin/end messages for all tracks currently tracked.
   void SendLifetimeMessages(MediaStreamTrackMetrics::LifetimeEvent event);
 
-  MediaStreamInterface* stream() { return stream_; }
-  MediaStreamTrackMetrics::StreamType stream_type() { return stream_type_; }
+  MediaStreamInterface* stream() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    return observer_->stream().get();
+  }
+
+  MediaStreamTrackMetrics::StreamType stream_type() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    return stream_type_;
+  }
 
  private:
-  typedef std::set<std::string> IdSet;
-
-  // webrtc::ObserverInterface implementation.
-  void OnChanged() override;
-
-  template <class T>
-  IdSet GetTrackIds(const std::vector<rtc::scoped_refptr<T> >& tracks) {
-    IdSet track_ids;
-    typename std::vector<rtc::scoped_refptr<T> >::const_iterator it =
-        tracks.begin();
-    for (; it != tracks.end(); ++it) {
-      track_ids.insert((*it)->id());
-    }
-    return track_ids;
-  }
+  void OnChanged(const IdSet& audio_track_ids, const IdSet& video_track_ids);
 
   void ReportAddedAndRemovedTracks(
       const IdSet& new_ids,
@@ -72,10 +138,11 @@
   IdSet video_track_ids_;
 
   MediaStreamTrackMetrics::StreamType stream_type_;
-  rtc::scoped_refptr<MediaStreamInterface> stream_;
+  scoped_refptr<MediaStreamObserver> observer_;
 
   // Non-owning.
   MediaStreamTrackMetrics* owner_;
+  base::ThreadChecker thread_checker_;
 };
 
 namespace {
@@ -101,20 +168,26 @@
     MediaStreamTrackMetrics* owner)
     : has_reported_start_(false),
       has_reported_end_(false),
+      audio_track_ids_(GetTrackIds(stream->GetAudioTracks())),
+      video_track_ids_(GetTrackIds(stream->GetVideoTracks())),
       stream_type_(stream_type),
-      stream_(stream),
+      observer_(new MediaStreamObserver(
+            base::Bind(&MediaStreamTrackMetricsObserver::OnChanged,
+                       base::Unretained(this)),
+            base::ThreadTaskRunnerHandle::Get(),
+            stream)),
       owner_(owner) {
-  OnChanged();  // To populate initial tracks.
-  stream_->RegisterObserver(this);
 }
 
 MediaStreamTrackMetricsObserver::~MediaStreamTrackMetricsObserver() {
-  stream_->UnregisterObserver(this);
+  DCHECK(thread_checker_.CalledOnValidThread());
+  observer_->Unregister();
   SendLifetimeMessages(MediaStreamTrackMetrics::DISCONNECTED);
 }
 
 void MediaStreamTrackMetricsObserver::SendLifetimeMessages(
     MediaStreamTrackMetrics::LifetimeEvent event) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   if (event == MediaStreamTrackMetrics::CONNECTED) {
     // Both ICE CONNECTED and COMPLETED can trigger the first
     // start-of-life event, so we only report the first.
@@ -146,33 +219,31 @@
   }
 }
 
-void MediaStreamTrackMetricsObserver::OnChanged() {
-  AudioTrackVector all_audio_tracks = stream_->GetAudioTracks();
-  IdSet all_audio_track_ids = GetTrackIds(all_audio_tracks);
-
-  VideoTrackVector all_video_tracks = stream_->GetVideoTracks();
-  IdSet all_video_track_ids = GetTrackIds(all_video_tracks);
+void MediaStreamTrackMetricsObserver::OnChanged(
+    const IdSet& audio_track_ids, const IdSet& video_track_ids) {
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   // We only report changes after our initial report, and never after
   // our last report.
   if (has_reported_start_ && !has_reported_end_) {
-    ReportAddedAndRemovedTracks(all_audio_track_ids,
+    ReportAddedAndRemovedTracks(audio_track_ids,
                                 audio_track_ids_,
                                 MediaStreamTrackMetrics::AUDIO_TRACK);
-    ReportAddedAndRemovedTracks(all_video_track_ids,
+    ReportAddedAndRemovedTracks(video_track_ids,
                                 video_track_ids_,
                                 MediaStreamTrackMetrics::VIDEO_TRACK);
   }
 
   // We always update our sets of tracks.
-  audio_track_ids_ = all_audio_track_ids;
-  video_track_ids_ = all_video_track_ids;
+  audio_track_ids_ = audio_track_ids;
+  video_track_ids_ = video_track_ids;
 }
 
 void MediaStreamTrackMetricsObserver::ReportAddedAndRemovedTracks(
     const IdSet& new_ids,
     const IdSet& old_ids,
     MediaStreamTrackMetrics::TrackType track_type) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(has_reported_start_ && !has_reported_end_);
 
   IdSet added_tracks = base::STLSetDifference<IdSet>(new_ids, old_ids);
@@ -187,6 +258,7 @@
     const IdSet& ids,
     MediaStreamTrackMetrics::TrackType track_type,
     MediaStreamTrackMetrics::LifetimeEvent event) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   for (IdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
     owner_->SendLifetimeMessage(*it, track_type, event, stream_type_);
   }
diff --git a/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
index dcf1b13..d18c04f 100644
--- a/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
+++ b/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
 #include "content/renderer/media/webrtc/media_stream_track_metrics.h"
 #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -78,16 +82,56 @@
 
 class MediaStreamTrackMetricsTest : public testing::Test {
  public:
+  MediaStreamTrackMetricsTest() : signaling_thread_("signaling_thread") {}
   void SetUp() override {
     metrics_.reset(new MockMediaStreamTrackMetrics());
     stream_ = new rtc::RefCountedObject<MockMediaStream>("stream");
+    signaling_thread_.Start();
   }
 
   void TearDown() override {
+    signaling_thread_.Stop();
     metrics_.reset();
     stream_ = NULL;
   }
 
+  // Adds an audio track to |stream_| on the signaling thread to simulate how
+  // notifications will be fired in Chrome.
+  template <typename TrackType>
+  void AddTrack(TrackType* track) {
+    // Explicitly casting to this type is necessary since the
+    // MediaStreamInterface has two methods with the same name.
+    typedef bool (MediaStreamInterface::*AddTrack)(TrackType*);
+    base::RunLoop run_loop;
+    signaling_thread_.task_runner()->PostTaskAndReply(FROM_HERE,
+        base::Bind(
+            base::IgnoreResult<AddTrack>(&MediaStreamInterface::AddTrack),
+            stream_, track),
+        run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  template <typename TrackType>
+  void RemoveTrack(TrackType* track) {
+    // Explicitly casting to this type is necessary since the
+    // MediaStreamInterface has two methods with the same name.
+    typedef bool (MediaStreamInterface::*RemoveTrack)(TrackType*);
+    base::RunLoop run_loop;
+    signaling_thread_.task_runner()->PostTaskAndReply(FROM_HERE,
+        base::Bind(
+            base::IgnoreResult<RemoveTrack>(&MediaStreamInterface::RemoveTrack),
+            stream_, track),
+        run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
+  // Convenience methods to cast the mock track types into their webrtc
+  // equivalents.
+  void AddAudioTrack(AudioTrackInterface* track) { AddTrack(track); }
+  void RemoveAudioTrack(AudioTrackInterface* track) { RemoveTrack(track); }
+  void AddVideoTrack(VideoTrackInterface* track) { AddTrack(track); }
+  void RemoveVideoTrack(VideoTrackInterface* track) { RemoveTrack(track); }
+
   scoped_refptr<MockAudioTrackInterface> MakeAudioTrack(std::string id) {
     return new rtc::RefCountedObject<MockAudioTrackInterface>(id);
   }
@@ -98,6 +142,9 @@
 
   scoped_ptr<MockMediaStreamTrackMetrics> metrics_;
   scoped_refptr<MediaStreamInterface> stream_;
+
+  base::MessageLoopForUI message_loop_;
+  base::Thread signaling_thread_;
 };
 
 TEST_F(MediaStreamTrackMetricsTest, MakeUniqueId) {
@@ -262,7 +309,7 @@
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::CONNECTED,
                                   MediaStreamTrackMetrics::RECEIVED_STREAM));
-  stream_->AddTrack(added.get());
+  AddAudioTrack(added.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("initial",
@@ -321,7 +368,7 @@
   // This gets added after we start observing, but no lifetime message
   // should be sent at this point since the call is not connected. It
   // should get sent only once it gets connected.
-  stream_->AddTrack(second.get());
+  AddAudioTrack(second.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("first",
@@ -350,7 +397,7 @@
 
   // This happens after the call is disconnected so no lifetime
   // message should be sent.
-  stream_->RemoveTrack(first.get());
+  RemoveAudioTrack(first.get());
 }
 
 TEST_F(MediaStreamTrackMetricsTest, RemoteStreamMultipleDisconnects) {
@@ -374,7 +421,7 @@
   metrics_->IceConnectionChange(
       PeerConnectionInterface::kIceConnectionDisconnected);
   metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
-  stream_->RemoveTrack(audio.get());
+  RemoveAudioTrack(audio.get());
 }
 
 TEST_F(MediaStreamTrackMetricsTest, RemoteStreamConnectDisconnectTwice) {
@@ -400,7 +447,7 @@
         PeerConnectionInterface::kIceConnectionDisconnected);
   }
 
-  stream_->RemoveTrack(audio.get());
+  RemoveAudioTrack(audio.get());
 }
 
 TEST_F(MediaStreamTrackMetricsTest, LocalStreamRemovedNoDisconnect) {
@@ -465,33 +512,33 @@
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::CONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->AddTrack(audio2.get());
+  AddAudioTrack(audio2.get());
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("video2",
                                   MediaStreamTrackMetrics::VIDEO_TRACK,
                                   MediaStreamTrackMetrics::CONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->AddTrack(video2.get());
+  AddVideoTrack(video2.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("audio1",
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::DISCONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->RemoveTrack(audio1.get());
+  RemoveAudioTrack(audio1.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("audio3",
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::CONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->AddTrack(audio3.get());
+  AddAudioTrack(audio3.get());
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("video3",
                                   MediaStreamTrackMetrics::VIDEO_TRACK,
                                   MediaStreamTrackMetrics::CONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->AddTrack(video3.get());
+  AddVideoTrack(video3.get());
 
   // Add back audio1
   EXPECT_CALL(*metrics_,
@@ -499,33 +546,33 @@
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::CONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->AddTrack(audio1.get());
+  AddAudioTrack(audio1.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("audio2",
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::DISCONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->RemoveTrack(audio2.get());
+  RemoveAudioTrack(audio2.get());
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("video2",
                                   MediaStreamTrackMetrics::VIDEO_TRACK,
                                   MediaStreamTrackMetrics::DISCONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->RemoveTrack(video2.get());
+  RemoveVideoTrack(video2.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("audio1",
                                   MediaStreamTrackMetrics::AUDIO_TRACK,
                                   MediaStreamTrackMetrics::DISCONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->RemoveTrack(audio1.get());
+  RemoveAudioTrack(audio1.get());
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("video1",
                                   MediaStreamTrackMetrics::VIDEO_TRACK,
                                   MediaStreamTrackMetrics::DISCONNECTED,
                                   MediaStreamTrackMetrics::SENT_STREAM));
-  stream_->RemoveTrack(video1.get());
+  RemoveVideoTrack(video1.get());
 
   EXPECT_CALL(*metrics_,
               SendLifetimeMessage("audio3",
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 1bc3c05..e203c60 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -174,7 +174,8 @@
 }
 
 PeerConnectionDependencyFactory::~PeerConnectionDependencyFactory() {
-  CleanupPeerConnectionFactory();
+  DVLOG(1) << "~PeerConnectionDependencyFactory()";
+  DCHECK(pc_factory_.get() == NULL);
   if (aec_dump_message_filter_.get())
     aec_dump_message_filter_->RemoveDelegate(this);
 }
@@ -268,6 +269,11 @@
   return pc_factory_;
 }
 
+
+void PeerConnectionDependencyFactory::WillDestroyCurrentMessageLoop() {
+  CleanupPeerConnectionFactory();
+}
+
 void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
   DCHECK(!pc_factory_.get());
   DCHECK(!signaling_thread_);
@@ -279,6 +285,7 @@
 
   DVLOG(1) << "PeerConnectionDependencyFactory::CreatePeerConnectionFactory()";
 
+  base::MessageLoop::current()->AddDestructionObserver(this);
   // To allow sending to the signaling/worker threads.
   jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
   jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
@@ -584,6 +591,7 @@
 }
 
 void PeerConnectionDependencyFactory::CleanupPeerConnectionFactory() {
+  DVLOG(1) << "PeerConnectionDependencyFactory::CleanupPeerConnectionFactory()";
   pc_factory_ = NULL;
   if (network_manager_) {
     // The network manager needs to free its resources on the thread they were
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index 67eae9d..07375dd 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -9,6 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/files/file.h"
+#include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "content/common/content_export.h"
 #include "content/public/renderer/render_process_observer.h"
@@ -56,6 +57,7 @@
 // Object factory for RTC PeerConnections.
 class CONTENT_EXPORT PeerConnectionDependencyFactory
     : NON_EXPORTED_BASE(public base::NonThreadSafe),
+      NON_EXPORTED_BASE(base::MessageLoop::DestructionObserver),
       NON_EXPORTED_BASE(public AecDumpMessageFilter::AecDumpDelegate) {
  public:
   PeerConnectionDependencyFactory(
@@ -170,6 +172,11 @@
   virtual void StartLocalAudioTrack(WebRtcLocalAudioTrack* audio_track);
 
  private:
+  // Implement base::MessageLoop::DestructionObserver.
+  // This makes sure the libjingle PeerConnectionFactory is released before
+  // the renderer message loop is destroyed.
+  virtual void WillDestroyCurrentMessageLoop() override;
+
   // Creates |pc_factory_|, which in turn is used for
   // creating PeerConnection objects.
   void CreatePeerConnectionFactory();
diff --git a/content/renderer/media/webrtc/video_destination_handler.cc b/content/renderer/media/webrtc/video_destination_handler.cc
index 6e25469..0e2ba8e 100644
--- a/content/renderer/media/webrtc/video_destination_handler.cc
+++ b/content/renderer/media/webrtc/video_destination_handler.cc
@@ -157,16 +157,24 @@
       MediaStreamVideoSource::kUnknownFrameRate,
       media::PIXEL_FORMAT_YV12);
 
-  libyuv::ARGBToI420(src_data,
-                     src_stride,
-                     new_frame->data(media::VideoFrame::kYPlane),
-                     new_frame->stride(media::VideoFrame::kYPlane),
-                     new_frame->data(media::VideoFrame::kUPlane),
-                     new_frame->stride(media::VideoFrame::kUPlane),
-                     new_frame->data(media::VideoFrame::kVPlane),
-                     new_frame->stride(media::VideoFrame::kVPlane),
-                     width,
-                     height);
+  // TODO(magjed): Chrome OS is not ready for switching from BGRA to ARGB.
+  // Remove this once http://crbug/434007 is fixed. We have a corresponding
+  // problem when we send frames to the effects plugin in PepperVideoSourceHost.
+#if defined(OS_CHROMEOS)
+  auto libyuv_xxxx_to_i420 = &libyuv::BGRAToI420;
+#else
+  auto libyuv_xxxx_to_i420 = &libyuv::ARGBToI420;
+#endif
+  libyuv_xxxx_to_i420(src_data,
+                      src_stride,
+                      new_frame->data(media::VideoFrame::kYPlane),
+                      new_frame->stride(media::VideoFrame::kYPlane),
+                      new_frame->data(media::VideoFrame::kUPlane),
+                      new_frame->stride(media::VideoFrame::kUPlane),
+                      new_frame->data(media::VideoFrame::kVPlane),
+                      new_frame->stride(media::VideoFrame::kVPlane),
+                      width,
+                      height);
 
   delegate_->DeliverFrame(new_frame, format);
 }
diff --git a/content/renderer/pepper/pepper_video_source_host.cc b/content/renderer/pepper/pepper_video_source_host.cc
index b75eabb..49efee2 100644
--- a/content/renderer/pepper/pepper_video_source_host.cc
+++ b/content/renderer/pepper/pepper_video_source_host.cc
@@ -224,16 +224,24 @@
   const uint8* src_v = frame->data(media::VideoFrame::kVPlane) +
                        (center * vert_crop + horiz_crop) / 2;
 
-  libyuv::I420ToARGB(src_y,
-                     frame->stride(media::VideoFrame::kYPlane),
-                     src_u,
-                     frame->stride(media::VideoFrame::kUPlane),
-                     src_v,
-                     frame->stride(media::VideoFrame::kVPlane),
-                     bitmap_pixels,
-                     bitmap->rowBytes(),
-                     dst_width,
-                     dst_height);
+  // TODO(magjed): Chrome OS is not ready for switching from BGRA to ARGB.
+  // Remove this once http://crbug/434007 is fixed. We have a corresponding
+  // problem when we receive frames from the effects plugin in PpFrameWriter.
+#if defined(OS_CHROMEOS)
+  auto libyuv_i420_to_xxxx = &libyuv::I420ToBGRA;
+#else
+  auto libyuv_i420_to_xxxx = &libyuv::I420ToARGB;
+#endif
+  libyuv_i420_to_xxxx(src_y,
+                      frame->stride(media::VideoFrame::kYPlane),
+                      src_u,
+                      frame->stride(media::VideoFrame::kUPlane),
+                      src_v,
+                      frame->stride(media::VideoFrame::kVPlane),
+                      bitmap_pixels,
+                      bitmap->rowBytes(),
+                      dst_width,
+                      dst_height);
 
   ppapi::HostResource host_resource;
   host_resource.SetHostResource(pp_instance(), shared_image_->GetReference());
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 6984b13..713dffd 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -623,8 +623,11 @@
 
 #if defined(ENABLE_WEBRTC)
   RTCPeerConnectionHandler::DestructAllHandlers();
-
-  peer_connection_factory_.reset();
+  // |peer_connection_factory_| cannot be deleted until after the main message
+  // loop has been destroyed.  This is because there may be pending tasks that
+  // hold on to objects produced by the PC factory that depend on threads owned
+  // by the PC factory.  Once those tasks have been freed, the factory can be
+  // deleted.
 #endif
   RemoveFilter(vc_manager_->video_capture_message_filter());
   vc_manager_.reset();
@@ -1345,7 +1348,10 @@
                          params.hidden,
                          params.never_visible,
                          params.next_page_id,
-                         params.screen_info);
+                         params.initial_size,
+                         params.enable_auto_resize,
+                         params.min_size,
+                         params.max_size);
 }
 
 GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 7dc2da8..bc75a42 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -2494,4 +2494,25 @@
   EXPECT_LE(late_nav_reported_start, after_navigation);
 }
 
+class RenderViewImplInitialSizeTest : public RenderViewImplTest {
+ public:
+  RenderViewImplInitialSizeTest()
+      : RenderViewImplTest(), initial_size_(200, 100) {}
+
+ protected:
+  virtual scoped_ptr<ViewMsg_Resize_Params> InitialSizeParams() override {
+    scoped_ptr<ViewMsg_Resize_Params> initial_size_params(
+        new ViewMsg_Resize_Params());
+    initial_size_params->new_size = initial_size_;
+    return initial_size_params.Pass();
+  }
+
+  gfx::Size initial_size_;
+};
+
+TEST_F(RenderViewImplInitialSizeTest, InitialSize) {
+  ASSERT_EQ(initial_size_, view_->GetSize());
+  ASSERT_EQ(initial_size_, gfx::Size(view_->GetWebView()->size()));
+}
+
 }  // namespace content
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 56a719e..6897573 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -643,7 +643,7 @@
 
 RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
     : RenderWidget(blink::WebPopupTypeNone,
-                   params->screen_info,
+                   params->initial_size.screen_info,
                    params->swapped_out,
                    params->hidden,
                    params->never_visible),
@@ -790,6 +790,12 @@
 
   OnSetRendererPrefs(params->renderer_prefs);
 
+  if (!params->enable_auto_resize) {
+    OnResize(params->initial_size);
+  } else {
+    OnEnableAutoResize(params->min_size, params->max_size);
+  }
+
   new MHTMLGenerator(this);
 #if defined(OS_MACOSX)
   new TextInputClientObserver(this);
@@ -1142,7 +1148,10 @@
     bool hidden,
     bool never_visible,
     int32 next_page_id,
-    const blink::WebScreenInfo& screen_info) {
+    const ViewMsg_Resize_Params& initial_size,
+    bool enable_auto_resize,
+    const gfx::Size& min_size,
+    const gfx::Size& max_size) {
   DCHECK(routing_id != MSG_ROUTING_NONE);
   RenderViewImplParams params(opener_id,
                               window_was_created_with_opener,
@@ -1159,7 +1168,10 @@
                               hidden,
                               never_visible,
                               next_page_id,
-                              screen_info);
+                              initial_size,
+                              enable_auto_resize,
+                              min_size,
+                              max_size);
   RenderViewImpl* render_view = NULL;
   if (g_create_render_view_impl)
     render_view = g_create_render_view_impl(&params);
@@ -1672,6 +1684,9 @@
   // TODO(vangelis): Can we tell if the new view will be a background page?
   bool never_visible = false;
 
+  ViewMsg_Resize_Params initial_size = ViewMsg_Resize_Params();
+  initial_size.screen_info = screen_info_;
+
   // The initial hidden state for the RenderViewImpl here has to match what the
   // browser will eventually decide for the given disposition. Since we have to
   // return from this call synchronously, we just have to make our best guess
@@ -1693,7 +1708,11 @@
       params.disposition == NEW_BACKGROUND_TAB,  // hidden
       never_visible,
       1,  // next_page_id
-      screen_info_);
+      initial_size,
+      false, // enable_auto_resize
+      gfx::Size(), // min_size
+      gfx::Size() // max_size
+  );
   view->opened_by_user_gesture_ = params.user_gesture;
 
   // Record whether the creator frame is trying to suppress the opener field.
@@ -4045,6 +4064,9 @@
     const WebSize& inner_viewport_offset,
     const WebRect& touch_rect,
     const WebVector<WebRect>& target_rects) {
+  if (!switches::IsLinkDisambiguationPopupEnabled())
+    return false;
+
   // Never show a disambiguation popup when accessibility is enabled,
   // as this interferes with "touch exploration".
   AccessibilityMode accessibility_mode =
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 67adc19..be982b0 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -78,6 +78,7 @@
 struct PP_NetAddress_Private;
 struct FrameMsg_Navigate_Params;
 struct ViewMsg_PostMessage_Params;
+struct ViewMsg_Resize_Params;
 struct ViewMsg_StopFinding_Params;
 
 namespace base {
@@ -178,7 +179,10 @@
                                 bool hidden,
                                 bool never_visible,
                                 int32 next_page_id,
-                                const blink::WebScreenInfo& screen_info);
+                                const ViewMsg_Resize_Params& initial_size,
+                                bool enable_auto_resize,
+                                const gfx::Size& min_size,
+                                const gfx::Size& max_size);
 
   // Used by content_layouttest_support to hook into the creation of
   // RenderViewImpls.
diff --git a/content/renderer/render_view_impl_params.cc b/content/renderer/render_view_impl_params.cc
index 6864a3d..5a39b4c 100644
--- a/content/renderer/render_view_impl_params.cc
+++ b/content/renderer/render_view_impl_params.cc
@@ -22,7 +22,10 @@
     bool hidden,
     bool never_visible,
     int32 next_page_id,
-    const blink::WebScreenInfo& screen_info)
+    const ViewMsg_Resize_Params& initial_size,
+    bool enable_auto_resize,
+    const gfx::Size& min_size,
+    const gfx::Size& max_size)
     : opener_id(opener_id),
       window_was_created_with_opener(window_was_created_with_opener),
       renderer_prefs(renderer_prefs),
@@ -38,7 +41,10 @@
       hidden(hidden),
       never_visible(never_visible),
       next_page_id(next_page_id),
-      screen_info(screen_info) {}
+      initial_size(initial_size),
+      enable_auto_resize(enable_auto_resize),
+      min_size(min_size),
+      max_size(max_size) {}
 
 RenderViewImplParams::~RenderViewImplParams() {}
 
diff --git a/content/renderer/render_view_impl_params.h b/content/renderer/render_view_impl_params.h
index ad9a26c..173b6a4 100644
--- a/content/renderer/render_view_impl_params.h
+++ b/content/renderer/render_view_impl_params.h
@@ -9,7 +9,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "content/common/content_export.h"
-#include "content/common/view_message_enums.h"
+#include "ui/gfx/geometry/size.h"
+
+struct ViewMsg_Resize_Params;
 
 namespace blink {
 struct WebScreenInfo;
@@ -37,7 +39,10 @@
                        bool hidden,
                        bool never_visible,
                        int32 next_page_id,
-                       const blink::WebScreenInfo& screen_info);
+                       const ViewMsg_Resize_Params& initial_size,
+                       bool enable_auto_resize,
+                       const gfx::Size& min_size,
+                       const gfx::Size& max_size);
   ~RenderViewImplParams();
 
   int32 opener_id;
@@ -55,7 +60,10 @@
   bool hidden;
   bool never_visible;
   int32 next_page_id;
-  const blink::WebScreenInfo& screen_info;
+  const ViewMsg_Resize_Params& initial_size;
+  bool enable_auto_resize;
+  gfx::Size min_size;
+  gfx::Size max_size;
 };
 
 }  // namespace content
diff --git a/content/shell/renderer/test_runner/event_sender.cc b/content/shell/renderer/test_runner/event_sender.cc
index 4c90eb4..c16eba0 100644
--- a/content/shell/renderer/test_runner/event_sender.cc
+++ b/content/shell/renderer/test_runner/event_sender.cc
@@ -357,6 +357,7 @@
   void ZoomPageOut();
   void SetPageZoomFactor(double factor);
   void SetPageScaleFactor(gin::Arguments* args);
+  void SetPageScaleFactorLimits(gin::Arguments* args);
   void ClearTouchPoints();
   void ReleaseTouchPoint(unsigned index);
   void UpdateTouchPoint(unsigned index, double x, double y);
@@ -483,6 +484,8 @@
       .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
       .SetMethod("setPageZoomFactor", &EventSenderBindings::SetPageZoomFactor)
       .SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
+      .SetMethod("setPageScaleFactorLimits",
+                 &EventSenderBindings::SetPageScaleFactorLimits)
       .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
       .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
       .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
@@ -640,6 +643,20 @@
                               static_cast<int>(x), static_cast<int>(y));
 }
 
+void EventSenderBindings::SetPageScaleFactorLimits(gin::Arguments* args) {
+  if (!sender_)
+    return;
+  float min_scale_factor;
+  float max_scale_factor;
+  if (args->PeekNext().IsEmpty())
+    return;
+  args->GetNext(&min_scale_factor);
+  if (args->PeekNext().IsEmpty())
+    return;
+  args->GetNext(&max_scale_factor);
+  sender_->SetPageScaleFactorLimits(min_scale_factor, max_scale_factor);
+}
+
 void EventSenderBindings::ClearTouchPoints() {
   if (sender_)
     sender_->ClearTouchPoints();
@@ -1463,10 +1480,13 @@
 }
 
 void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
-  view_->setPageScaleFactorLimits(scale_factor, scale_factor);
   view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
 }
 
+void EventSender::SetPageScaleFactorLimits(float min_scale, float max_scale) {
+  view_->setPageScaleFactorLimits(min_scale, max_scale);
+}
+
 void EventSender::ClearTouchPoints() {
   touch_points_.clear();
 }
diff --git a/content/shell/renderer/test_runner/event_sender.h b/content/shell/renderer/test_runner/event_sender.h
index 2d4b99a..71f72d7 100644
--- a/content/shell/renderer/test_runner/event_sender.h
+++ b/content/shell/renderer/test_runner/event_sender.h
@@ -99,7 +99,10 @@
   void ZoomPageOut();
   void SetPageZoomFactor(double zoom_factor);
 
+  // TODO: Move these into Internals once PageScaleConstraints are moved out of
+  // Source/web. crbug.com/434450.
   void SetPageScaleFactor(float scale_factor, int x, int y);
+  void SetPageScaleFactorLimits(float min_scale, float max_scale);
 
   void ClearTouchPoints();
   void ReleaseTouchPoint(unsigned index);
diff --git a/content/test/run_all_unittests.cc b/content/test/run_all_unittests.cc
index b6170ad..9c86597 100644
--- a/content/test/run_all_unittests.cc
+++ b/content/test/run_all_unittests.cc
@@ -8,7 +8,16 @@
 #include "content/public/test/unittest_test_suite.h"
 #include "content/test/content_test_suite.h"
 
+#if defined(OS_ANDROID)
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#endif
+
 int main(int argc, char** argv) {
+#if defined(OS_ANDROID)
+  // Android wants to call GetChannelId() (even though GPU channels
+  // are not getting created in content_unittests).
+  content::BrowserGpuChannelHostFactory::Initialize(false);
+#endif
 #if !defined(OS_IOS)
   content::InitializeMojo();
 #endif
diff --git a/device/usb/usb_device_impl.cc b/device/usb/usb_device_impl.cc
index 57f3d63..6fa3d50 100644
--- a/device/usb/usb_device_impl.cc
+++ b/device/usb/usb_device_impl.cc
@@ -157,6 +157,12 @@
         continue;
       }
 
+#if defined(OS_CHROMEOS)
+      value = udev_device_get_devnode(device.get());
+      if (value) {
+        devnode_ = value;
+      }
+#endif
       value = udev_device_get_sysattr_value(device.get(), "manufacturer");
       if (value) {
         manufacturer_ = base::UTF8ToUTF16(value);
@@ -207,10 +213,9 @@
 
     ui_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&chromeos::PermissionBrokerClient::RequestUsbAccess,
+        base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess,
                    base::Unretained(client),
-                   vendor_id(),
-                   product_id(),
+                   devnode_,
                    interface_id,
                    base::Bind(&OnRequestUsbAccessReplied,
                               base::ThreadTaskRunnerHandle::Get(),
diff --git a/device/usb/usb_device_impl.h b/device/usb/usb_device_impl.h
index e962c6d..379d401 100644
--- a/device/usb/usb_device_impl.h
+++ b/device/usb/usb_device_impl.h
@@ -76,6 +76,11 @@
   void CacheStrings();
   bool strings_cached_;
 #endif
+#if defined(OS_CHROMEOS)
+  // On Chrome OS save the devnode string for requesting path access from
+  // permission broker.
+  std::string devnode_;
+#endif
 
   // The active configuration descriptor is not read immediately but cached for
   // later use.
diff --git a/extensions/browser/guest_view/guest_view_base.cc b/extensions/browser/guest_view/guest_view_base.cc
index 01c7a5e..6679985 100644
--- a/extensions/browser/guest_view/guest_view_base.cc
+++ b/extensions/browser/guest_view/guest_view_base.cc
@@ -419,12 +419,6 @@
 
 void GuestViewBase::RenderViewReady() {
   GuestReady();
-  content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
-  if (auto_size_enabled_) {
-    rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
-  } else {
-    rvh->DisableAutoResize(element_size_);
-  }
 }
 
 void GuestViewBase::WebContentsDestroyed() {
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index 262bae2..52ac29c 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -76,9 +76,12 @@
     "contexts": ["blessed_extension"],
     "dependencies": ["permission:appview"]
   },
+  // Note that exposing this doesn't necessarily expose AppView,
+  // appViewEmbedderInternal is required for that.
+  // See http://crbug.com/437891.
   "appViewGuestInternal": {
     "internal": true,
-    "channel": "dev",
+    "channel": "stable",
     "contexts": ["blessed_extension"]
   },
   "bluetooth": {
diff --git a/extensions/test/data/web_view/apitest/main.js b/extensions/test/data/web_view/apitest/main.js
index 2c8d15f..977b063 100644
--- a/extensions/test/data/web_view/apitest/main.js
+++ b/extensions/test/data/web_view/apitest/main.js
@@ -222,8 +222,6 @@
   webview.setAttribute('maxheight', 110);
 
   webview.addEventListener('sizechanged', function(e) {
-    embedder.test.assertEq(0, e.oldWidth);
-    embedder.test.assertEq(0, e.oldHeight);
     embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210);
     embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110);
     embedder.test.succeed();
@@ -248,7 +246,6 @@
   webview.addEventListener('sizechanged', function(e) {
     switch (step) {
       case 1:
-        embedder.test.assertEq(0, e.oldHeight);
         embedder.test.assertEq(200, e.newHeight);
         // Change the maxheight to verify that we see the change.
         webview.maxheight = 50;
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index e1e9650..120e6db 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "7.8",
+  "version": "7.11",
   "entries": [
     {
       "id": 1,
@@ -175,7 +175,11 @@
       "id": 11,
       "description": "Limit max texure size to 4096 on Macs with Intel GPUs",
       "os": {
-        "type": "macosx"
+        "type": "macosx",
+        "version": {
+          "op": "<",
+          "value": "10.9"
+        }
       },
       "vendor_id": "0x8086",
       "features": [
@@ -212,7 +216,11 @@
       "id": 14,
       "description": "Limit max texure size and cube map texture size to 4096 on Macs with AMD GPUs",
       "os": {
-        "type": "macosx"
+        "type": "macosx",
+        "version": {
+          "op": "<",
+          "value": "10.9"
+        }
       },
       "vendor_id": "0x1002",
       "features": [
@@ -1055,7 +1063,7 @@
         "type": "android",
         "version": {
           "op": "<=",
-          "value": "5.0.0"
+          "value": "5.0.1"
         }
       },
       "gl_vendor": "NVIDIA.*",
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc
index 53343f6..eabf9b2 100644
--- a/gpu/config/gpu_info_collector_win.cc
+++ b/gpu/config/gpu_info_collector_win.cc
@@ -665,6 +665,45 @@
     return;
   }
 
+  // Track D3D Shader Model (if available)
+  const std::string& shader_version =
+      context_gpu_info.vertex_shader_version;
+
+  // Only gather if this is the first time we're seeing
+  // a non-empty shader version string.
+  if (!shader_version.empty() &&
+      basic_gpu_info->vertex_shader_version.empty()) {
+
+    // Note: do not reorder, used by UMA_HISTOGRAM below
+    enum ShaderModel {
+      SHADER_MODEL_UNKNOWN,
+      SHADER_MODEL_2_0,
+      SHADER_MODEL_3_0,
+      SHADER_MODEL_4_0,
+      SHADER_MODEL_4_1,
+      SHADER_MODEL_5_0,
+      NUM_SHADER_MODELS
+    };
+
+    ShaderModel shader_model = SHADER_MODEL_UNKNOWN;
+
+    if (shader_version == "5.0") {
+      shader_model = SHADER_MODEL_5_0;
+    } else if (shader_version == "4.1") {
+      shader_model = SHADER_MODEL_4_1;
+    } else if (shader_version == "4.0") {
+      shader_model = SHADER_MODEL_4_0;
+    } else if (shader_version == "3.0") {
+      shader_model = SHADER_MODEL_3_0;
+    } else if (shader_version == "2.0") {
+      shader_model = SHADER_MODEL_2_0;
+    }
+
+    UMA_HISTOGRAM_ENUMERATION("GPU.D3DShaderModel",
+                              shader_model,
+                              NUM_SHADER_MODELS);
+  }
+
   MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
 
   basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
index 11e8e81..b9f5e3a 100644
--- a/gpu/config/software_rendering_list_json.cc
+++ b/gpu/config/software_rendering_list_json.cc
@@ -18,7 +18,7 @@
 {
   "name": "software rendering list",
   // Please update the version number whenever you change this file.
-  "version": "9.12",
+  "version": "9.13",
   "entries": [
     {
       "id": 1,
@@ -1165,6 +1165,23 @@
       "features": [
         "all"
       ]
+    },
+    {
+      "id": 104,
+      "description": "GPU raster broken on PowerVR Rogue",
+      "cr_bugs": [436331],
+      "os": {
+        "type": "android",
+        "version": {
+          "op": "<",
+          "value": "5.0"
+        }
+      },
+      "gl_renderer": "PowerVR Rogue.*",
+      "features": [
+        "accelerated_2d_canvas",
+        "gpu_rasterization"
+      ]
     }
   ]
 }
diff --git a/media/blink/buffered_data_source.cc b/media/blink/buffered_data_source.cc
index 16128f1..55d94d3 100644
--- a/media/blink/buffered_data_source.cc
+++ b/media/blink/buffered_data_source.cc
@@ -20,9 +20,12 @@
 // of FFmpeg.
 const int kInitialReadBufferSize = 32768;
 
-// Number of cache misses we allow for a single Read() before signaling an
-// error.
-const int kNumCacheMissRetries = 3;
+// Number of cache misses or read failures we allow for a single Read() before
+// signaling an error.
+const int kLoaderRetries = 3;
+
+// The number of milliseconds to wait before retrying a failed load.
+const int kLoaderFailedRetryDelayMs = 250;
 
 }  // namespace
 
@@ -424,8 +427,19 @@
     // Stop the resource load if it failed.
     loader_->Stop();
 
-    if (status == BufferedResourceLoader::kCacheMiss &&
-        read_op_->retries() < kNumCacheMissRetries) {
+    if (read_op_->retries() < kLoaderRetries) {
+      // Allow some resiliency against sporadic network failures or intentional
+      // cancellations due to a system suspend / resume.  Here we treat failed
+      // reads as a cache miss so long as we haven't exceeded max retries.
+      if (status == BufferedResourceLoader::kFailed) {
+        render_task_runner_->PostDelayedTask(
+            FROM_HERE, base::Bind(&BufferedDataSource::ReadCallback,
+                                  weak_factory_.GetWeakPtr(),
+                                  BufferedResourceLoader::kCacheMiss, 0),
+            base::TimeDelta::FromMilliseconds(kLoaderFailedRetryDelayMs));
+        return;
+      }
+
       read_op_->IncrementRetries();
 
       // Recreate a loader starting from where we last left off until the
diff --git a/media/blink/buffered_data_source_unittest.cc b/media/blink/buffered_data_source_unittest.cc
index a76beb0..688a7a0 100644
--- a/media/blink/buffered_data_source_unittest.cc
+++ b/media/blink/buffered_data_source_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/bind.h"
 #include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "media/base/media_log.h"
 #include "media/base/mock_filters.h"
 #include "media/base/test_helpers.h"
@@ -17,7 +18,9 @@
 
 using ::testing::_;
 using ::testing::Assign;
+using ::testing::DoAll;
 using ::testing::Invoke;
+using ::testing::InvokeWithoutArgs;
 using ::testing::InSequence;
 using ::testing::NiceMock;
 using ::testing::StrictMock;
@@ -410,6 +413,34 @@
   Stop();
 }
 
+TEST_F(BufferedDataSourceTest, Http_RetryOnError) {
+  InitializeWith206Response();
+
+  // Read to advance our position.
+  EXPECT_CALL(*this, ReadCallback(kDataSize));
+  EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
+  ReadAt(0);
+  ReceiveData(kDataSize);
+
+  // Issue a pending read but trigger an error to force a retry.
+  EXPECT_CALL(*this, ReadCallback(kDataSize));
+  EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, (kDataSize * 2) - 1));
+  ReadAt(kDataSize);
+  base::RunLoop run_loop;
+  EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
+      .WillOnce(
+          DoAll(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit),
+                Invoke(data_source_.get(),
+                       &MockBufferedDataSource::CreateMockResourceLoader)));
+  loader()->didFail(url_loader(), response_generator_->GenerateError());
+  run_loop.Run();
+  Respond(response_generator_->Generate206(kDataSize));
+  ReceiveData(kDataSize);
+  FinishLoading();
+  EXPECT_FALSE(data_source_->loading());
+  Stop();
+}
+
 TEST_F(BufferedDataSourceTest, File_Retry) {
   InitializeWithFileResponse();
 
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
index 65ecd11..015f6b3 100644
--- a/net/http/http_server_properties_impl.cc
+++ b/net/http/http_server_properties_impl.cc
@@ -204,12 +204,16 @@
   if (g_forced_alternate_protocol)
     return true;
   AlternateProtocolMap::const_iterator it = alternate_protocol_map_.Get(server);
-  if (it != alternate_protocol_map_.end() &&
-      it->second.probability >= alternate_protocol_probability_threshold_) {
-    return true;
+  if (it != alternate_protocol_map_.end())
+    return it->second.probability >= alternate_protocol_probability_threshold_;
+
+  auto canonical = GetCanonicalHost(server);
+  if (canonical == canonical_host_to_origin_map_.end() ||
+      canonical->second.Equals(server)) {
+    return false;
   }
 
-  return GetCanonicalHost(server) != canonical_host_to_origin_map_.end();
+  return HasAlternateProtocol(canonical->second);
 }
 
 std::string HttpServerPropertiesImpl::GetCanonicalSuffix(
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc
index 1c016b7..2ef6b12 100644
--- a/net/http/http_server_properties_impl_unittest.cc
+++ b/net/http/http_server_properties_impl_unittest.cc
@@ -445,6 +445,36 @@
   EXPECT_EQ(".c.youtube.com", impl_.GetCanonicalSuffix(canonical_port_pair));
 }
 
+TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBelowThreshold) {
+  impl_.SetAlternateProtocolProbabilityThreshold(0.02);
+
+  HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
+  HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
+  AlternateProtocolInfo canonical_protocol(1234, QUIC, 0.01);
+
+  impl_.SetAlternateProtocol(canonical_port_pair,
+                             canonical_protocol.port,
+                             canonical_protocol.protocol,
+                             canonical_protocol.probability);
+  EXPECT_FALSE(impl_.HasAlternateProtocol(canonical_port_pair));
+  EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
+}
+
+TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) {
+  impl_.SetAlternateProtocolProbabilityThreshold(0.02);
+
+  HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
+  HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
+  AlternateProtocolInfo canonical_protocol(1234, QUIC, 0.03);
+
+  impl_.SetAlternateProtocol(canonical_port_pair,
+                             canonical_protocol.port,
+                             canonical_protocol.protocol,
+                             canonical_protocol.probability);
+  EXPECT_TRUE(impl_.HasAlternateProtocol(canonical_port_pair));
+  EXPECT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
+}
+
 TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) {
   HostPortPair test_host_port_pair("foo.c.youtube.com", 80);
   HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 73a5aec..c8d3195 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -718,6 +718,7 @@
                          read_buffer_->size(),
                          base::Bind(&QuicClientSession::OnReadComplete,
                                     weak_factory_.GetWeakPtr()));
+  UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING);
   if (rv == ERR_IO_PENDING) {
     num_packets_read_ = 0;
     return;
diff --git a/net/quic/quic_default_packet_writer.cc b/net/quic/quic_default_packet_writer.cc
index d851dfb..177d292 100644
--- a/net/quic/quic_default_packet_writer.cc
+++ b/net/quic/quic_default_packet_writer.cc
@@ -6,6 +6,7 @@
 
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/metrics/sparse_histogram.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -24,12 +25,14 @@
 QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
 
 WriteResult QuicDefaultPacketWriter::WritePacket(
-    const char* buffer, size_t buf_len,
+    const char* buffer,
+    size_t buf_len,
     const net::IPAddressNumber& self_address,
     const net::IPEndPoint& peer_address) {
   scoped_refptr<StringIOBuffer> buf(
       new StringIOBuffer(std::string(buffer, buf_len)));
   DCHECK(!IsWriteBlocked());
+  base::TimeTicks now = base::TimeTicks::Now();
   int rv = socket_->Write(buf.get(),
                           buf_len,
                           base::Bind(&QuicDefaultPacketWriter::OnWriteComplete,
@@ -45,6 +48,13 @@
     }
   }
 
+  base::TimeDelta delta = base::TimeTicks::Now() - now;
+  if (status == WRITE_STATUS_OK) {
+    UMA_HISTOGRAM_TIMES("Net.QuicSession.PacketWriteTime.Synchronous", delta);
+  } else if (status == WRITE_STATUS_BLOCKED) {
+    UMA_HISTOGRAM_TIMES("Net.QuicSession.PacketWriteTime.Asynchronous", delta);
+  }
+
   return WriteResult(status, rv);
 }
 
diff --git a/sync/engine/syncer_unittest.cc b/sync/engine/syncer_unittest.cc
index 46fa871..8d97d33 100644
--- a/sync/engine/syncer_unittest.cc
+++ b/sync/engine/syncer_unittest.cc
@@ -4448,6 +4448,217 @@
   }
 }
 
+// Tests specifically related to bookmark (and therefore no client tags) sync
+// logic. Entities without client tags have custom logic in parts of the code,
+// and hence are not covered by e.g. the Undeletion tests below.
+class SyncerBookmarksTest : public SyncerTest {
+ public:
+  SyncerBookmarksTest() : metahandle_(syncable::kInvalidMetaHandle) {
+  }
+
+  void Create() {
+    WriteTransaction trans(FROM_HERE, UNITTEST, directory());
+    MutableEntry bookmark(
+        &trans, CREATE, BOOKMARKS, ids_.root(), "clientname");
+    ASSERT_TRUE(bookmark.good());
+    bookmark.PutIsUnsynced(true);
+    bookmark.PutSyncing(false);
+    bookmark.PutSpecifics(DefaultBookmarkSpecifics());
+    EXPECT_FALSE(bookmark.GetIsUnappliedUpdate());
+    EXPECT_FALSE(bookmark.GetId().ServerKnows());
+    metahandle_ = bookmark.GetMetahandle();
+    local_id_ = bookmark.GetId();
+  }
+
+  void Delete() {
+    WriteTransaction trans(FROM_HERE, UNITTEST, directory());
+    MutableEntry entry(&trans, GET_BY_HANDLE, metahandle_);
+    ASSERT_TRUE(entry.good());
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    // The order of setting IS_UNSYNCED vs IS_DEL matters. See
+    // WriteNode::Tombstone().
+    entry.PutIsUnsynced(true);
+    entry.PutIsDel(true);
+    entry.PutSyncing(false);
+  }
+
+  void Undelete() {
+    WriteTransaction trans(FROM_HERE, UNITTEST, directory());
+    MutableEntry entry(&trans, GET_BY_HANDLE, metahandle_);
+    ASSERT_TRUE(entry.good());
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_TRUE(entry.GetIsDel());
+    entry.PutIsDel(false);
+    entry.PutIsUnsynced(true);
+    entry.PutSyncing(false);
+  }
+
+  int64 GetMetahandleOfTag() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+    EXPECT_TRUE(entry.good());
+    if (!entry.good()) {
+      return syncable::kInvalidMetaHandle;
+    }
+    return entry.GetMetahandle();
+  }
+
+  Id GetServerId() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+    EXPECT_TRUE(entry.good());
+    if (!entry.good()) {
+      return Id();
+    }
+    return entry.GetId();
+  }
+
+  void ExpectUnsyncedCreation() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_FALSE(entry.GetIsDel());
+    EXPECT_FALSE(entry.GetServerIsDel());  // Never been committed.
+    EXPECT_LT(entry.GetBaseVersion(), 0);
+    EXPECT_TRUE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+  }
+
+  void ExpectUnsyncedUndeletion() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_FALSE(entry.GetIsDel());
+    EXPECT_TRUE(entry.GetServerIsDel());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_TRUE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+    EXPECT_TRUE(entry.GetId().ServerKnows());
+  }
+
+  void ExpectUnsyncedEdit() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_FALSE(entry.GetIsDel());
+    EXPECT_FALSE(entry.GetServerIsDel());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_TRUE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+    EXPECT_TRUE(entry.GetId().ServerKnows());
+  }
+
+  void ExpectUnsyncedDeletion() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_TRUE(entry.GetIsDel());
+    EXPECT_FALSE(entry.GetServerIsDel());
+    EXPECT_TRUE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_GE(entry.GetServerVersion(), 0);
+  }
+
+  void ExpectSyncedAndCreated() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_FALSE(entry.GetIsDel());
+    EXPECT_FALSE(entry.GetServerIsDel());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_EQ(entry.GetBaseVersion(), entry.GetServerVersion());
+    EXPECT_FALSE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+  }
+
+  void ExpectSyncedAndDeleted() {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_TRUE(entry.GetIsDel());
+    EXPECT_TRUE(entry.GetServerIsDel());
+    EXPECT_FALSE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_GE(entry.GetServerVersion(), 0);
+  }
+
+ protected:
+  syncable::Id local_id_;
+  int64 metahandle_;
+};
+
+TEST_F(SyncerBookmarksTest, CreateSyncThenDeleteSync) {
+  Create();
+  ExpectUnsyncedCreation();
+  SyncShareNudge();
+  ExpectSyncedAndCreated();
+  Delete();
+  ExpectUnsyncedDeletion();
+  SyncShareNudge();
+  ExpectSyncedAndDeleted();
+}
+
+TEST_F(SyncerBookmarksTest, CreateThenDeleteBeforeSync) {
+  Create();
+  ExpectUnsyncedCreation();
+  Delete();
+
+  // Deleting before the initial commit should result in not needing to send
+  // the delete to the server. It will still be in an unsynced state, but with
+  // IS_UNSYNCED set to false.
+  {
+    syncable::ReadTransaction trans(FROM_HERE, directory());
+    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
+
+    EXPECT_EQ(metahandle_, entry.GetMetahandle());
+    EXPECT_TRUE(entry.GetIsDel());
+    EXPECT_FALSE(entry.GetServerIsDel());
+    EXPECT_FALSE(entry.GetIsUnsynced());
+    EXPECT_FALSE(entry.GetIsUnappliedUpdate());
+    EXPECT_EQ(entry.GetBaseVersion(), -1);
+    EXPECT_EQ(entry.GetServerVersion(), 0);
+  }
+}
+
+TEST_F(SyncerBookmarksTest, LocalDeleteRemoteChangeConflict) {
+  Create();
+  ExpectUnsyncedCreation();
+  SyncShareNudge();
+  ExpectSyncedAndCreated();
+  Delete();
+  ExpectUnsyncedDeletion();
+
+  // Trigger a getupdates that modifies the bookmark. The update should  be
+  // clobbered by the local delete.
+  mock_server_->AddUpdateBookmark(GetServerId(), Id(), "dummy", 10, 10,
+                                  local_cache_guid(), local_id_.GetServerId());
+
+  SyncShareNudge();
+  ExpectSyncedAndDeleted();
+}
+
+TEST_F(SyncerBookmarksTest, CreateThenDeleteDuringCommit) {
+  Create();
+  ExpectUnsyncedCreation();
+
+  // In the middle of the initial creation commit, perform a deletion.
+  // This should trigger performing two consecutive commit cycles, resulting
+  // in the bookmark being both deleted and synced.
+  mock_server_->SetMidCommitCallback(
+      base::Bind(&SyncerBookmarksTest::Delete, base::Unretained(this)));
+
+  SyncShareNudge();
+  ExpectSyncedAndDeleted();
+}
+
 // Test what happens if a client deletes, then recreates, an object very
 // quickly.  It is possible that the deletion gets sent as a commit, and
 // the undelete happens during the commit request.  The principle here
@@ -4477,12 +4688,12 @@
   void Create() {
     WriteTransaction trans(FROM_HERE, UNITTEST, directory());
     MutableEntry perm_folder(
-        &trans, CREATE, BOOKMARKS, ids_.root(), "clientname");
+        &trans, CREATE, PREFERENCES, ids_.root(), "clientname");
     ASSERT_TRUE(perm_folder.good());
     perm_folder.PutUniqueClientTag(client_tag_);
     perm_folder.PutIsUnsynced(true);
     perm_folder.PutSyncing(false);
-    perm_folder.PutSpecifics(DefaultBookmarkSpecifics());
+    perm_folder.PutSpecifics(DefaultPreferencesSpecifics());
     EXPECT_FALSE(perm_folder.GetIsUnappliedUpdate());
     EXPECT_FALSE(perm_folder.GetId().ServerKnows());
     metahandle_ = perm_folder.GetMetahandle();
@@ -4494,8 +4705,10 @@
     MutableEntry entry(&trans, GET_BY_CLIENT_TAG, client_tag_);
     ASSERT_TRUE(entry.good());
     EXPECT_EQ(metahandle_, entry.GetMetahandle());
-    entry.PutIsDel(true);
+    // The order of setting IS_UNSYNCED vs IS_DEL matters. See
+    // WriteNode::Tombstone().
     entry.PutIsUnsynced(true);
+    entry.PutIsDel(true);
     entry.PutSyncing(false);
   }
 
@@ -4527,7 +4740,7 @@
     EXPECT_EQ(metahandle_, entry.GetMetahandle());
     EXPECT_FALSE(entry.GetIsDel());
     EXPECT_FALSE(entry.GetServerIsDel());  // Never been committed.
-    EXPECT_GE(0, entry.GetBaseVersion());
+    EXPECT_LT(entry.GetBaseVersion(), 0);
     EXPECT_TRUE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
   }
@@ -4539,7 +4752,7 @@
     EXPECT_EQ(metahandle_, entry.GetMetahandle());
     EXPECT_FALSE(entry.GetIsDel());
     EXPECT_TRUE(entry.GetServerIsDel());
-    EXPECT_EQ(0, entry.GetBaseVersion());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
     EXPECT_TRUE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
     EXPECT_TRUE(entry.GetId().ServerKnows());
@@ -4552,7 +4765,7 @@
     EXPECT_EQ(metahandle_, entry.GetMetahandle());
     EXPECT_FALSE(entry.GetIsDel());
     EXPECT_FALSE(entry.GetServerIsDel());
-    EXPECT_LT(0, entry.GetBaseVersion());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
     EXPECT_TRUE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
     EXPECT_TRUE(entry.GetId().ServerKnows());
@@ -4567,8 +4780,8 @@
     EXPECT_FALSE(entry.GetServerIsDel());
     EXPECT_TRUE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
-    EXPECT_LT(0, entry.GetBaseVersion());
-    EXPECT_LT(0, entry.GetServerVersion());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_GE(entry.GetServerVersion(), 0);
   }
 
   void ExpectSyncedAndCreated() {
@@ -4578,7 +4791,7 @@
     EXPECT_EQ(metahandle_, entry.GetMetahandle());
     EXPECT_FALSE(entry.GetIsDel());
     EXPECT_FALSE(entry.GetServerIsDel());
-    EXPECT_LT(0, entry.GetBaseVersion());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
     EXPECT_EQ(entry.GetBaseVersion(), entry.GetServerVersion());
     EXPECT_FALSE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
@@ -4593,8 +4806,8 @@
     EXPECT_TRUE(entry.GetServerIsDel());
     EXPECT_FALSE(entry.GetIsUnsynced());
     EXPECT_FALSE(entry.GetIsUnappliedUpdate());
-    EXPECT_GE(0, entry.GetBaseVersion());
-    EXPECT_GE(0, entry.GetServerVersion());
+    EXPECT_GE(entry.GetBaseVersion(), 0);
+    EXPECT_GE(entry.GetServerVersion(), 0);
   }
 
  protected:
@@ -4793,7 +5006,7 @@
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry entry(&trans, GET_BY_HANDLE, metahandle_);
-    mock_server_->AddUpdateTombstone(entry.GetId());
+    mock_server_->AddUpdateTombstone(entry.GetId(), PREFERENCES);
   }
   SyncShareNudge();
 
@@ -4835,7 +5048,7 @@
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry entry(&trans, GET_BY_HANDLE, metahandle_);
-    mock_server_->AddUpdateTombstone(entry.GetId());
+    mock_server_->AddUpdateTombstone(entry.GetId(), PREFERENCES);
   }
   SyncShareNudge();
 
@@ -4903,22 +5116,16 @@
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry entry(&trans, GET_BY_HANDLE, metahandle_);
-    mock_server_->AddUpdateBookmark(
-        entry.GetId(),
-        entry.GetParentId(),
-        "Thadeusz", 100, 1000,
-        local_cache_guid(), local_id_.GetServerId());
+    mock_server_->AddUpdatePref(
+        entry.GetId().GetServerId(),
+        entry.GetParentId().GetServerId(),
+        client_tag_, 100, 1000);
   }
   mock_server_->SetLastUpdateClientTag(client_tag_);
   SyncShareNudge();
   EXPECT_EQ(0, session_->status_controller().TotalNumConflictingItems());
   EXPECT_EQ(1, mock_server_->GetAndClearNumGetUpdatesRequests());
   ExpectSyncedAndCreated();
-  {
-    syncable::ReadTransaction trans(FROM_HERE, directory());
-    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
-    EXPECT_EQ("Thadeusz", entry.GetNonUniqueName());
-  }
 }
 
 TEST_F(SyncerUndeletionTest, OtherClientUndeletesImmediately) {
@@ -4958,22 +5165,16 @@
   {
     syncable::ReadTransaction trans(FROM_HERE, directory());
     Entry entry(&trans, GET_BY_HANDLE, metahandle_);
-    mock_server_->AddUpdateBookmark(
-        entry.GetId(),
-        entry.GetParentId(),
-        "Thadeusz", 100, 1000,
-        local_cache_guid(), local_id_.GetServerId());
+    mock_server_->AddUpdatePref(
+        entry.GetId().GetServerId(),
+        entry.GetParentId().GetServerId(),
+        client_tag_, 100, 1000);
   }
   mock_server_->SetLastUpdateClientTag(client_tag_);
   SyncShareNudge();
   EXPECT_EQ(0, session_->status_controller().TotalNumConflictingItems());
   EXPECT_EQ(1, mock_server_->GetAndClearNumGetUpdatesRequests());
   ExpectSyncedAndCreated();
-  {
-    syncable::ReadTransaction trans(FROM_HERE, directory());
-    Entry entry(&trans, GET_BY_HANDLE, metahandle_);
-    EXPECT_EQ("Thadeusz", entry.GetNonUniqueName());
-  }
 }
 
 enum {
diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc
index 5d11b6f..9c59409 100644
--- a/sync/syncable/directory.cc
+++ b/sync/syncable/directory.cc
@@ -1280,14 +1280,11 @@
                       trans))
         return false;
     }
-    // Server-unknown items that are locally deleted should not be sent up to
-    // the server.  They must be !IS_UNSYNCED.
-    if (!SyncAssert(!(!id.ServerKnows() && e.GetIsDel() && e.GetIsUnsynced()),
-                    FROM_HERE,
-                    "Locally deleted item must not be unsynced.",
-                    trans)) {
-      return false;
-    }
+
+    // Previously we would assert that locally deleted items that have never
+    // been synced must not be sent to the server (IS_UNSYNCED must be false).
+    // This is not always true in the case that an item is deleted while the
+    // initial commit is in flight. See crbug.com/426865.
   }
   return true;
 }
diff --git a/sync/syncable/mutable_entry.cc b/sync/syncable/mutable_entry.cc
index b1c1ff4..0aa37e7 100644
--- a/sync/syncable/mutable_entry.cc
+++ b/sync/syncable/mutable_entry.cc
@@ -170,7 +170,9 @@
     // - Let us delete this entry permanently through
     //   DirectoryBackingStore::DropDeletedEntries() when we next restart sync.
     //   This will save memory and avoid crbug.com/125381.
-    if (!GetId().ServerKnows()) {
+    // Note: do not unset IsUnsynced if the syncer is in the middle of
+    // attempting to commit this entity.
+    if (!GetId().ServerKnows() && !GetSyncing()) {
       PutIsUnsynced(false);
     }
   }
diff --git a/sync/test/engine/mock_connection_manager.cc b/sync/test/engine/mock_connection_manager.cc
index ef3022e..4e42f54 100644
--- a/sync/test/engine/mock_connection_manager.cc
+++ b/sync/test/engine/mock_connection_manager.cc
@@ -394,8 +394,9 @@
       last_commit_response().entryresponse(0).response_type());
 
   if (last_sent_commit().entries(0).deleted()) {
+    ModelType type = GetModelType(last_sent_commit().entries(0));
     AddUpdateTombstone(syncable::Id::CreateFromServerId(
-        last_sent_commit().entries(0).id_string()));
+        last_sent_commit().entries(0).id_string()), type);
   } else {
     sync_pb::SyncEntity* ent = GetUpdateResponse()->add_entries();
     ent->CopyFrom(last_sent_commit().entries(0));
@@ -425,7 +426,9 @@
   return GetMutableLastUpdate();
 }
 
-void MockConnectionManager::AddUpdateTombstone(const syncable::Id& id) {
+void MockConnectionManager::AddUpdateTombstone(
+    const syncable::Id& id,
+    ModelType type) {
   // Tombstones have only the ID set and dummy values for the required fields.
   sync_pb::SyncEntity* ent = GetUpdateResponse()->add_entries();
   ent->set_id_string(id.GetServerId());
@@ -434,14 +437,15 @@
   ent->set_deleted(true);
 
   // Make sure we can still extract the ModelType from this tombstone.
-  ent->mutable_specifics()->mutable_bookmark();
+  AddDefaultFieldValue(type, ent->mutable_specifics());
 }
 
 void MockConnectionManager::SetLastUpdateDeleted() {
   // Tombstones have only the ID set.  Wipe anything else.
   string id_string = GetMutableLastUpdate()->id_string();
+  ModelType type = GetModelType(*GetMutableLastUpdate());
   GetUpdateResponse()->mutable_entries()->RemoveLast();
-  AddUpdateTombstone(syncable::Id::CreateFromServerId(id_string));
+  AddUpdateTombstone(syncable::Id::CreateFromServerId(id_string), type);
 }
 
 void MockConnectionManager::SetLastUpdateOriginatorFields(
diff --git a/sync/test/engine/mock_connection_manager.h b/sync/test/engine/mock_connection_manager.h
index 19e483b..611d949 100644
--- a/sync/test/engine/mock_connection_manager.h
+++ b/sync/test/engine/mock_connection_manager.h
@@ -145,7 +145,7 @@
   // Add a deleted item.  Deletion records typically contain no
   // additional information beyond the deletion, and no specifics.
   // The server may send the originator fields.
-  void AddUpdateTombstone(const syncable::Id& id);
+  void AddUpdateTombstone(const syncable::Id& id, ModelType type);
 
   void SetLastUpdateDeleted();
   void SetLastUpdateServerTag(const std::string& tag);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 113c961..d31d2cc 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -9775,6 +9775,14 @@
   </summary>
 </histogram>
 
+<histogram name="GPU.D3DShaderModel" enum="ShaderModel">
+  <owner>jmadill@chromium.org</owner>
+  <summary>
+    ANGLE's currently active D3D shader model version. Logged once every startup
+    of the GPU process, on Windows only.
+  </summary>
+</histogram>
+
 <histogram name="GPU.InitializeOneOffTime" units="microseconds">
   <owner>vangelis@chromium.org</owner>
   <summary>
@@ -17518,6 +17526,14 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.AsyncRead">
+  <owner>rch@chromium.org</owner>
+  <summary>
+    True if the result of reading a packet from the network was ERR_IO_PENDING.
+    Recorded for each packet when Read() returns.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.BlockedFrames.Received">
   <owner>rtenneti@chromium.org</owner>
   <summary>
@@ -17817,6 +17833,15 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.PacketWriteTime">
+  <owner>rch@chromium.org</owner>
+  <summary>
+    The time taken to Write() a QUIC packet to the socket. Recorded for each
+    packet when it is sent. The suffix specifies if the write completed
+    synchonously or asynchronously.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.PublicResetAddressMismatch"
     enum="QuicAddressMismatch">
   <owner>wtc@chromium.org</owner>
@@ -29919,6 +29944,8 @@
   <summary>
     Records a histogram of the reason why downloads are marked as being
     malicious or clean by the improved SafeBrowsing binary download protection.
+    Note that UNSUPPORTED_URL_SCHEME was split out of the INVALID_URL bucket in
+    M41.
   </summary>
 </histogram>
 
@@ -40406,6 +40433,12 @@
   </summary>
 </histogram>
 
+<histogram name="WrenchMenu.MenuAction" enum="WretchMenuAction">
+  <owner>ainslie@chromium.org</owner>
+  <owner>edwardjung@chromium.org</owner>
+  <summary>Number of times that each menu item is clicked.</summary>
+</histogram>
+
 <histogram name="WrenchMenu.RecentTabsSubMenu" enum="RecentTabsAction">
   <owner>rpop@chromium.org</owner>
   <summary>
@@ -40414,6 +40447,14 @@
   </summary>
 </histogram>
 
+<histogram name="WrenchMenu.TimeToAction">
+  <owner>ainslie@chromium.org</owner>
+  <owner>edwardjung@chromium.org</owner>
+  <summary>
+    The time a user takes to select a menu itme after opening the menu.
+  </summary>
+</histogram>
+
 <histogram name="ZeroSuggest.AllResults">
   <owner>hfung@chromium.org</owner>
   <summary>
@@ -47927,6 +47968,7 @@
   <int value="-1662447331" label="wake-on-packets"/>
   <int value="-1654344175" label="disable-extension-info-dialog"/>
   <int value="-1619757314" label="touch-scrolling-mode"/>
+  <int value="-1614912400" label="enable-link-disambiguation-popup"/>
   <int value="-1605567628" label="disable-overlay-scrollbar"/>
   <int value="-1596559650" label="max-tiles-for-interest-area"/>
   <int value="-1571841513" label="enable-devtools-experiments"/>
@@ -48091,6 +48133,7 @@
   <int value="880510010" label="enable-permissions-bubbles"/>
   <int value="887011602" label="enable-spelling-auto-correct"/>
   <int value="909439558" label="disable-device-discovery"/>
+  <int value="929462705" label="disable-link-disambiguation-popup"/>
   <int value="952558794" label="enable-remote-assistance"/>
   <int value="980396200" label="enable-new-korean-ime"/>
   <int value="1022992701" label="enable-origin-chip-always"/>
@@ -53127,6 +53170,7 @@
   <int value="19" label="ARCHIVE_WITHOUT_BINARIES"/>
   <int value="20" label="DOWNLOAD_DANGEROUS_HOST"/>
   <int value="21" label="DOWNLOAD_POTENTIALLY_UNWANTED"/>
+  <int value="22" label="UNSUPPORTED_URL_SCHEME"/>
 </enum>
 
 <enum name="SBClientDownloadExtensions" type="int">
@@ -53472,6 +53516,16 @@
   <int value="4" label="Expires before Jan 1, 2016"/>
 </enum>
 
+<enum name="ShaderModel" type="int">
+  <summary>The GPU's Direct3D shader model version.</summary>
+  <int value="0" label="SHADER_MODEL_UNKNOWN"/>
+  <int value="1" label="SHADER_MODEL_2_0"/>
+  <int value="2" label="SHADER_MODEL_3_0"/>
+  <int value="3" label="SHADER_MODEL_4_0"/>
+  <int value="4" label="SHADER_MODEL_4_1"/>
+  <int value="5" label="SHADER_MODEL_5_0"/>
+</enum>
+
 <enum name="ShelfAlignmentValue" type="int">
   <summary>
     The alignment of the shelf area (see ash/launcher/launcher_view.cc).
@@ -55972,6 +56026,53 @@
   <int value="3" label="Packaged App"/>
 </enum>
 
+<enum name="WretchMenuAction" type="int">
+  <int value="0" label="New tab"/>
+  <int value="1" label="New window"/>
+  <int value="2" label="New incognito window"/>
+  <int value="3" label="Show bookmark bar"/>
+  <int value="4" label="Show bookmark manager"/>
+  <int value="5" label="Import settings"/>
+  <int value="6" label="Bookmark page"/>
+  <int value="7" label="Bookmark all tabs"/>
+  <int value="8" label="Pin to start screen"/>
+  <int value="9" label="Restore tab"/>
+  <int value="10" label="Win desktop restart"/>
+  <int value="11" label="Win8 metro restart"/>
+  <int value="12" label="Win chromeos restart"/>
+  <int value="13" label="Distill page"/>
+  <int value="14" label="Save page"/>
+  <int value="15" label="Find"/>
+  <int value="16" label="Print"/>
+  <int value="17" label="Cut"/>
+  <int value="18" label="Copy"/>
+  <int value="19" label="Paste"/>
+  <int value="20" label="Create hosted app"/>
+  <int value="21" label="Create shortcuts"/>
+  <int value="22" label="Manage extensions"/>
+  <int value="23" label="Task manager"/>
+  <int value="24" label="Clear browsing data"/>
+  <int value="25" label="View source"/>
+  <int value="26" label="Dev tools"/>
+  <int value="27" label="Dev tools console"/>
+  <int value="28" label="Dev tools devices"/>
+  <int value="29" label="Profiling enabled"/>
+  <int value="30" label="Zoom minus"/>
+  <int value="31" label="Zoom plus"/>
+  <int value="32" label="Fullscreen"/>
+  <int value="33" label="Show history"/>
+  <int value="34" label="Show downloads"/>
+  <int value="35" label="Show sync setup"/>
+  <int value="36" label="Options"/>
+  <int value="37" label="About"/>
+  <int value="38" label="Help page via menu"/>
+  <int value="39" label="Feedback"/>
+  <int value="40" label="Toggle request tablet site"/>
+  <int value="41" label="Recent tab"/>
+  <int value="42" label="Open a bookmark"/>
+  <int value="43" label="Exit"/>
+</enum>
+
 <enum name="XMLHttpRequestSendArrayBufferOrView" type="int">
   <int value="0" label="XMLHttpRequestSendArrayBuffer"/>
   <int value="1" label="XMLHttpRequestSendArrayBufferView"/>
@@ -57044,6 +57145,12 @@
   <affected-histogram name="Net.TCP_Connection_Latency_Interval"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="IOMode" separator=".">
+  <suffix name="Synchronous"/>
+  <suffix name="Asynchronous"/>
+  <affected-histogram name="Net.QuicSession.PacketWriteTime"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="IPProtocolType" separator="_">
   <suffix name="UDP"/>
   <suffix name="TCP"/>
@@ -59729,6 +59836,52 @@
   <affected-histogram name="NewTabPage.DefaultPageType"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="WrenchMenuActionTimings" separator=".">
+  <suffix name="NewTab"/>
+  <suffix name="NewWindow"/>
+  <suffix name="NewIncognitoWindow"/>
+  <suffix name="ShowBookmarkBar"/>
+  <suffix name="ShowBookmarkMgr"/>
+  <suffix name="ImportSettings"/>
+  <suffix name="BookmarkPage"/>
+  <suffix name="BookmarkAllTabs"/>
+  <suffix name="PinToStartScreen"/>
+  <suffix name="RestoreTab"/>
+  <suffix name="WinDesktopRestart"/>
+  <suffix name="Win8MetroRestart"/>
+  <suffix name="ChromeOSRestart"/>
+  <suffix name="DistillPage"/>
+  <suffix name="SavePage"/>
+  <suffix name="Find"/>
+  <suffix name="Print"/>
+  <suffix name="Cut"/>
+  <suffix name="Copy"/>
+  <suffix name="Paste"/>
+  <suffix name="CreateHostedApp"/>
+  <suffix name="CreateShortcuts"/>
+  <suffix name="ManageExtensions"/>
+  <suffix name="TaskManager"/>
+  <suffix name="ClearBrowsingData"/>
+  <suffix name="ViewSource"/>
+  <suffix name="DevTools"/>
+  <suffix name="DevToolsConsole"/>
+  <suffix name="DevToolsDevices"/>
+  <suffix name="ProfilingEnabled"/>
+  <suffix name="ZoomMinus"/>
+  <suffix name="ZoomPlus"/>
+  <suffix name="EnterFullScreen"/>
+  <suffix name="ShowHistory"/>
+  <suffix name="ShowDownloads"/>
+  <suffix name="ShowSyncSetup"/>
+  <suffix name="Settings"/>
+  <suffix name="About"/>
+  <suffix name="HelpPage"/>
+  <suffix name="Feedback"/>
+  <suffix name="RequestTabletSite"/>
+  <suffix name="Exit"/>
+  <affected-histogram name="WrenchMenu.TimeToAction"/>
+</histogram_suffixes>
+
 </histogram_suffixes_list>
 
 </histogram-configuration>
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc
index 2163397..24d0d55 100644
--- a/ui/base/ui_base_switches.cc
+++ b/ui/base/ui_base_switches.cc
@@ -27,6 +27,10 @@
 // Disables controls that support touch base text editing.
 const char kDisableTouchEditing[] = "disable-touch-editing";
 
+// Enables a zoomed popup bubble that allows the user to select a link.
+const char kEnableLinkDisambiguationPopup[] =
+    "enable-link-disambiguation-popup";
+
 // Enables an experimental focus manager to track text input clients.
 const char kEnableTextInputFocusManager[] = "enable-text-input-focus-manager";
 
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h
index 629f9af..b4d503b 100644
--- a/ui/base/ui_base_switches.h
+++ b/ui/base/ui_base_switches.h
@@ -21,6 +21,7 @@
 UI_BASE_EXPORT extern const char kDisableTouchAdjustment[];
 UI_BASE_EXPORT extern const char kDisableTouchDragDrop[];
 UI_BASE_EXPORT extern const char kDisableTouchEditing[];
+UI_BASE_EXPORT extern const char kEnableLinkDisambiguationPopup[];
 UI_BASE_EXPORT extern const char kEnableTextInputFocusManager[];
 UI_BASE_EXPORT extern const char kEnableTouchDragDrop[];
 UI_BASE_EXPORT extern const char kEnableTouchEditing[];
diff --git a/ui/base/ui_base_switches_util.cc b/ui/base/ui_base_switches_util.cc
index 58b85c7..7a89264 100644
--- a/ui/base/ui_base_switches_util.cc
+++ b/ui/base/ui_base_switches_util.cc
@@ -9,6 +9,18 @@
 
 namespace switches {
 
+bool IsLinkDisambiguationPopupEnabled() {
+#if defined(OS_ANDROID)
+  return true;
+#else
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableLinkDisambiguationPopup)) {
+    return true;
+  }
+  return false;
+#endif
+}
+
 bool IsTextInputFocusManagerEnabled() {
   return CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kEnableTextInputFocusManager);
diff --git a/ui/base/ui_base_switches_util.h b/ui/base/ui_base_switches_util.h
index de08d1c..213aed6 100644
--- a/ui/base/ui_base_switches_util.h
+++ b/ui/base/ui_base_switches_util.h
@@ -9,6 +9,7 @@
 
 namespace switches {
 
+UI_BASE_EXPORT bool IsLinkDisambiguationPopupEnabled();
 UI_BASE_EXPORT bool IsTextInputFocusManagerEnabled();
 UI_BASE_EXPORT bool IsTouchDragDropEnabled();
 UI_BASE_EXPORT bool IsTouchEditingEnabled();
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc
index 4aadd66..1f88669 100644
--- a/ui/events/latency_info.cc
+++ b/ui/events/latency_info.cc
@@ -29,9 +29,6 @@
     CASE_TYPE(INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT);
     CASE_TYPE(WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT);
     CASE_TYPE(WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT);
-    CASE_TYPE(INPUT_EVENT_BROWSER_COMPOSITE_COMPONENT);
-    CASE_TYPE(INPUT_EVENT_BROWSER_SWAP_BUFFER_COMPONENT);
-    CASE_TYPE(INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT);
     CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT);
     CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT);
     CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT);
diff --git a/ui/events/latency_info.h b/ui/events/latency_info.h
index 00343af..454e561 100644
--- a/ui/events/latency_info.h
+++ b/ui/events/latency_info.h
@@ -54,13 +54,6 @@
   WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT,
   // Timestamp when a tab is requested to be shown.
   TAB_SHOW_COMPONENT,
-  // Timestamp of when the Browser process began compositing
-  INPUT_EVENT_BROWSER_COMPOSITE_COMPONENT,
-  // Timestamp of when the Browser process began swap buffers
-  INPUT_EVENT_BROWSER_SWAP_BUFFER_COMPONENT,
-  // Timestamp of when the gpu service began swap buffers, unlike
-  // INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT which measure after
-  INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT,
   // ---------------------------TERMINAL COMPONENT-----------------------------
   // TERMINAL COMPONENT is when we show the latency end in chrome://tracing.
   // Timestamp when the mouse event is acked from renderer and it does not
@@ -111,7 +104,7 @@
   };
 
   // Empirically determined constant based on a typical scroll sequence.
-  enum { kTypicalMaxComponentsPerLatencyInfo = 9 };
+  enum { kTypicalMaxComponentsPerLatencyInfo = 6 };
 
   enum { kMaxInputCoordinates = 2 };
 
diff --git a/ui/file_manager/gallery/js/image_editor/exif_encoder.js b/ui/file_manager/gallery/js/image_editor/exif_encoder.js
index 80fdef8..5874be3 100644
--- a/ui/file_manager/gallery/js/image_editor/exif_encoder.js
+++ b/ui/file_manager/gallery/js/image_editor/exif_encoder.js
@@ -87,7 +87,7 @@
   var pixelCount = this.metadata_.width * this.metadata_.height;
   var maxEncodedSize = 5000 * Math.min(10, 1 + pixelCount / 1000000);
 
-  var DATA_URL_PREFIX = 'data:' + this.mimeType + ';base64,';
+  var DATA_URL_PREFIX = 'data:' + this.metadata_.media.mimeType + ';base64,';
   var BASE64_BLOAT = 4 / 3;
   var maxDataURLLength =
       DATA_URL_PREFIX.length + Math.ceil(maxEncodedSize * BASE64_BLOAT);
diff --git a/ui/file_manager/gallery/js/image_editor/image_encoder.js b/ui/file_manager/gallery/js/image_editor/image_encoder.js
index 0cc5e65..78f2049 100644
--- a/ui/file_manager/gallery/js/image_editor/image_encoder.js
+++ b/ui/file_manager/gallery/js/image_editor/image_encoder.js
@@ -31,7 +31,7 @@
  */
 ImageEncoder.createMetadataEncoder = function(metadata) {
   var constructor =
-      (metadata && ImageEncoder.metadataEncoders[metadata.mimeType]) ||
+      (metadata && ImageEncoder.metadataEncoders[metadata.media.mimeType]) ||
       ImageEncoder.MetadataEncoder;
   return new constructor(metadata);
 };
@@ -73,7 +73,7 @@
   // WebKit does not support canvas.toBlob yet so canvas.toDataURL is
   // the only way to use the Chrome built-in image encoder.
   var dataURL =
-      canvas.toDataURL(metadataEncoder.getMetadata().mimeType, quality);
+      canvas.toDataURL(metadataEncoder.getMetadata().media.mimeType, quality);
   ImageUtil.trace.reportTimer('dataurl');
 
   var encodedImage = ImageEncoder.decodeDataURL(dataURL);
@@ -102,7 +102,8 @@
     appendSlice(ImageEncoder.stringToArrayBuffer(
         encodedImage, 0, encodedImage.length));
   }
-  var blob = new Blob(slices, {type: metadataEncoder.getMetadata().mimeType});
+  var blob = new Blob(slices,
+      {type: metadataEncoder.getMetadata().media.mimeType});
   ImageUtil.trace.reportTimer('blob');
   return blob;
 };
@@ -175,10 +176,10 @@
  */
 ImageEncoder.MetadataEncoder = function(original_metadata) {
   this.metadata_ = MetadataCache.cloneMetadata(original_metadata) || {};
-  if (this.metadata_.mimeType != 'image/jpeg') {
+  if (this.metadata_.media.mimeType !== 'image/jpeg') {
     // Chrome can only encode JPEG and PNG. Force PNG mime type so that we
     // can save to file and generate a thumbnail.
-    this.metadata_.mimeType = 'image/png';
+    this.metadata_.media.mimeType = 'image/png';
   }
 };
 
@@ -206,7 +207,7 @@
 ImageEncoder.MetadataEncoder.prototype.setThumbnailData =
     function(canvas, quality) {
   this.metadata_.thumbnailURL =
-      canvas.toDataURL(this.metadata_.mimeType, quality);
+      canvas.toDataURL(this.metadata_.media.mimeType, quality);
   delete this.metadata_.thumbnailTransform;
 };
 
diff --git a/ui/webui/resources/css/widgets.css b/ui/webui/resources/css/widgets.css
index e4c7a59..e4ff82a 100644
--- a/ui/webui/resources/css/widgets.css
+++ b/ui/webui/resources/css/widgets.css
@@ -270,6 +270,7 @@
 [is='action-link'][disabled] {
   color: #999;
   cursor: default;
+  pointer-events: none;
   text-decoration: none;
 }
 
diff --git a/ui/webui/resources/js/action_link.js b/ui/webui/resources/js/action_link.js
index 30685b0..5dea966 100644
--- a/ui/webui/resources/js/action_link.js
+++ b/ui/webui/resources/js/action_link.js
@@ -37,13 +37,11 @@
 
     /** @this {ActionLink} */
     createdCallback: function() {
-      // Links aren't tabble unless there's an [href] attribute set. Setting
-      // this adds undesirable "Open link in new tab..." context menu handlers
-      // so just manually add to tab order instead.
-      this.tabIndex = 0;
+      // Action links can start disabled (e.g. <a is="action-link" disabled>).
+      this.tabIndex = this.disabled ? -1 : 0;
 
       this.addEventListener('keydown', function(e) {
-        if (e.keyIdentifier == 'Enter') {
+        if (!this.disabled && e.keyIdentifier == 'Enter') {
           // Schedule a click asynchronously because other 'keydown' handlers
           // may still run later (e.g. document.addEventListener('keydown')).
           // Specifically options dialogs break when this timeout isn't here.
@@ -53,6 +51,34 @@
         }
       });
     },
+
+    /** @type {boolean} */
+    set disabled(disabled) {
+      if (disabled)
+        HTMLAnchorElement.prototype.setAttribute.call(this, 'disabled', '');
+      else
+        HTMLAnchorElement.prototype.removeAttribute.call(this, 'disabled');
+      this.tabIndex = disabled ? -1 : 0;
+    },
+    get disabled() {
+      return this.hasAttribute('disabled');
+    },
+
+    /** @override */
+    setAttribute: function(attr, val) {
+      if (attr.toLowerCase() == 'disabled')
+        this.disabled = true;
+      else
+        HTMLAnchorElement.prototype.setAttribute.apply(this, arguments);
+    },
+
+    /** @override */
+    removeAttribute: function(attr) {
+      if (attr.toLowerCase() == 'disabled')
+        this.disabled = false;
+      else
+        HTMLAnchorElement.prototype.removeAttribute.apply(this, arguments);
+    },
   },
   extends: 'a',
 });