Merge from Chromium at DEPS revision 37.0.2062.52

This commit was generated by merge_to_master.py.

Change-Id: Id79fecbf12a48cc7a1916e0a244695cbc1d298cf
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 def834f..8c5a157 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -2385,8 +2385,10 @@
     // Return true if the GeolocationPermissionAPI should be used.
     @CalledByNative
     private boolean useLegacyGeolocationPermissionAPI() {
-        // TODO (michaelbai): Need to verify whether this is correct when release.
-        return mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT;
+        // Always return true since we are not ready to swap the geolocation yet.
+        // TODO: If we decide not to migrate the geolocation, there are some unreachable
+        // code need to remove. http://crbug.com/396184.
+        return true;
     }
 
     //--------------------------------------------------------------------------------------------
diff --git a/apps/app_window.cc b/apps/app_window.cc
index 814d2e0..427cdc6 100644
--- a/apps/app_window.cc
+++ b/apps/app_window.cc
@@ -245,7 +245,8 @@
       has_been_shown_(false),
       can_send_events_(false),
       is_hidden_(false),
-      cached_always_on_top_(false) {
+      cached_always_on_top_(false),
+      requested_transparent_background_(false) {
   extensions::ExtensionsBrowserClient* client =
       extensions::ExtensionsBrowserClient::Get();
   CHECK(!client->IsGuestSession(context) || context->IsOffTheRecord())
@@ -284,6 +285,8 @@
   if (new_params.state == ui::SHOW_STATE_FULLSCREEN)
     new_params.always_on_top = false;
 
+  requested_transparent_background_ = new_params.transparent_background;
+
   native_app_window_.reset(delegate_->CreateNativeAppWindow(this, new_params));
 
   // Prevent the browser process from shutting down while this window exists.
@@ -751,6 +754,9 @@
   properties->SetBoolean("maximized", native_app_window_->IsMaximized());
   properties->SetBoolean("alwaysOnTop", IsAlwaysOnTop());
   properties->SetBoolean("hasFrameColor", native_app_window_->HasFrameColor());
+  properties->SetBoolean("alphaEnabled",
+                         requested_transparent_background_ &&
+                             native_app_window_->CanHaveAlphaEnabled());
 
   // These properties are undocumented and are to enable testing. Alpha is
   // removed to
diff --git a/apps/app_window.h b/apps/app_window.h
index f2e0e98..216ee3c 100644
--- a/apps/app_window.h
+++ b/apps/app_window.h
@@ -362,6 +362,11 @@
   // app.
   void WindowEventsReady();
 
+  // Whether the app window wants a transparent background.
+  bool requested_transparent_background() const {
+    return requested_transparent_background_;
+  }
+
  protected:
   virtual ~AppWindow();
 
@@ -558,6 +563,9 @@
   // taskbar.
   bool cached_always_on_top_;
 
+  // Whether |transparent_background| was set in the CreateParams.
+  bool requested_transparent_background_;
+
   DISALLOW_COPY_AND_ASSIGN(AppWindow);
 };
 
diff --git a/apps/ui/native_app_window.h b/apps/ui/native_app_window.h
index cde4c1d..fd0cc26 100644
--- a/apps/ui/native_app_window.h
+++ b/apps/ui/native_app_window.h
@@ -87,6 +87,10 @@
   virtual void SetContentSizeConstraints(const gfx::Size& min_size,
                                          const gfx::Size& max_size) = 0;
 
+  // Returns false if the underlying native window ignores alpha transparency
+  // when compositing.
+  virtual bool CanHaveAlphaEnabled() const = 0;
+
   virtual ~NativeAppWindow() {}
 };
 
diff --git a/apps/ui/views/native_app_window_views.cc b/apps/ui/views/native_app_window_views.cc
index 62b941d..da84d8a 100644
--- a/apps/ui/views/native_app_window_views.cc
+++ b/apps/ui/views/native_app_window_views.cc
@@ -27,14 +27,12 @@
       web_view_(NULL),
       widget_(NULL),
       frameless_(false),
-      transparent_background_(false),
       resizable_(false) {}
 
 void NativeAppWindowViews::Init(AppWindow* app_window,
                                 const AppWindow::CreateParams& create_params) {
   app_window_ = app_window;
   frameless_ = create_params.frame == AppWindow::FRAME_NONE;
-  transparent_background_ = create_params.transparent_background;
   resizable_ = create_params.resizable;
   size_constraints_.set_minimum_size(
       create_params.GetContentMinimumSize(gfx::Insets()));
@@ -53,6 +51,10 @@
   web_view_->SetWebContents(NULL);
 }
 
+void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() {
+  app_window_->OnNativeWindowChanged();
+}
+
 void NativeAppWindowViews::InitializeWindow(
     AppWindow* app_window,
     const AppWindow::CreateParams& create_params) {
@@ -260,7 +262,8 @@
 
 void NativeAppWindowViews::RenderViewCreated(
     content::RenderViewHost* render_view_host) {
-  if (transparent_background_) {
+  if (app_window_->requested_transparent_background() &&
+      CanHaveAlphaEnabled()) {
     content::RenderWidgetHostView* view = render_view_host->GetView();
     DCHECK(view);
     view->SetBackgroundOpaque(false);
@@ -398,4 +401,8 @@
   size_constraints_.set_maximum_size(max_size);
 }
 
+bool NativeAppWindowViews::CanHaveAlphaEnabled() const {
+  return widget_->IsTranslucentWindowOpacitySupported();
+}
+
 }  // namespace apps
diff --git a/apps/ui/views/native_app_window_views.h b/apps/ui/views/native_app_window_views.h
index bdebfde..917feca 100644
--- a/apps/ui/views/native_app_window_views.h
+++ b/apps/ui/views/native_app_window_views.h
@@ -52,6 +52,9 @@
   void Init(AppWindow* app_window,
             const AppWindow::CreateParams& create_params);
 
+  // Signal that CanHaveTransparentBackground has changed.
+  void OnCanHaveAlphaEnabledChanged();
+
   views::Widget* widget() { return widget_; }
 
   void set_window_for_testing(views::Widget* window) { widget_ = window; }
@@ -156,6 +159,7 @@
   virtual gfx::Size GetContentMaximumSize() const OVERRIDE;
   virtual void SetContentSizeConstraints(const gfx::Size& min_size,
                                          const gfx::Size& max_size) OVERRIDE;
+  virtual bool CanHaveAlphaEnabled() const OVERRIDE;
 
   // web_modal::WebContentsModalDialogHost implementation.
   virtual gfx::NativeView GetHostView() const OVERRIDE;
@@ -177,7 +181,6 @@
   scoped_ptr<SkRegion> draggable_region_;
 
   bool frameless_;
-  bool transparent_background_;
   bool resizable_;
   apps::SizeConstraints size_constraints_;
 
diff --git a/base/debug/dump_without_crashing.h b/base/debug/dump_without_crashing.h
index c46f446..b8ed174 100644
--- a/base/debug/dump_without_crashing.h
+++ b/base/debug/dump_without_crashing.h
@@ -14,6 +14,9 @@
 namespace debug {
 
 // Handler to silently dump the current process without crashing.
+// Before calling this function, call SetDumpWithoutCrashingFunction to pass a
+// function pointer, typically chrome!DumpProcessWithoutCrash.  See example code
+// in chrome_main.cc that does this for chrome.dll.
 BASE_EXPORT void DumpWithoutCrashing();
 
 // Sets a function that'll be invoked to dump the current process when
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index af4f2f7..2627e6a 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=284645
+LASTCHANGE=286032
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index e37d81a..835ce02 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=178617
+LASTCHANGE=179070
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index e06cadf..6dd4b3e 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2090,6 +2090,7 @@
   UpdateInnerViewportContainerSize();
   client_->OnCanDrawStateChanged(CanDraw());
   SetFullRootLayerDamage();
+  active_tree_->set_needs_update_draw_properties();
 }
 
 void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) {
diff --git a/chrome/VERSION b/chrome/VERSION
index 5d4cbde..ddf8350 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=37
 MINOR=0
 BUILD=2062
-PATCH=34
+PATCH=52
diff --git a/chrome/android/java/res/drawable/btn_infobar_blue.xml b/chrome/android/java/res/drawable/btn_infobar_blue.xml
index 73e7e0b..dafefd5 100644
--- a/chrome/android/java/res/drawable/btn_infobar_blue.xml
+++ b/chrome/android/java/res/drawable/btn_infobar_blue.xml
@@ -11,13 +11,13 @@
         android:state_selected="false">
         <shape>
             <solid android:color="@color/infobar_accent_blue" />
-            <corners android:radius="1dp" />
+            <corners android:radius="2dp" />
         </shape>
     </item>
     <item>
         <shape>
             <solid android:color="@color/infobar_accent_blue_pressed" />
-            <corners android:radius="1dp" />
+            <corners android:radius="2dp" />
         </shape>
     </item>
 </selector>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 9a54044..0f27a76 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -31,7 +31,7 @@
     <!-- Text size of the infobar message. -->
     <dimen name="infobar_text_size">16sp</dimen>
     <!-- Text size of text inside infobar buttons. -->
-    <dimen name="infobar_button_text_size">12sp</dimen>
+    <dimen name="infobar_button_text_size">14sp</dimen>
     <!-- Minimum width of an infobar. -->
     <dimen name="infobar_min_width">220dp</dimen>
     <!-- Margin between items in an infobar. -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java b/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java
index f2fdf3f..21e80f8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/NewTabPagePrefs.java
@@ -31,67 +31,90 @@
     }
 
     /**
-     * Set snapshot document list collapsed or uncollapsed state in preferences.
-     * @param isCollapsed {@code True} Whether we want the snapshot documents list to be collapsed.
+     * Sets whether the list of currently open tabs is collapsed (vs expanded) on the Recent Tabs
+     * page.
+     * @param isCollapsed Whether we want the currently open tabs list to be collapsed.
+     */
+    public void setCurrentlyOpenTabsCollapsed(boolean isCollapsed) {
+        nativeSetCurrentlyOpenTabsCollapsed(mNativeNewTabPagePrefs, isCollapsed);
+    }
+
+    /**
+     * Gets whether the list of currently open tabs is collapsed (vs expanded) on Recent Tabs page.
+     * @return Whether the list of currently open tabs is collapsed (vs expanded) on
+     *         the Recent Tabs page.
+     */
+    public boolean getCurrentlyOpenTabsCollapsed() {
+        return nativeGetCurrentlyOpenTabsCollapsed(mNativeNewTabPagePrefs);
+    }
+
+    /**
+     * Sets whether the list of snapshot documents is collapsed (vs expanded) on the Recent Tabs
+     * page.
+     * @param isCollapsed Whether we want the snapshot documents list to be collapsed.
      */
     public void setSnapshotDocumentCollapsed(boolean isCollapsed) {
         nativeSetSnapshotDocumentCollapsed(mNativeNewTabPagePrefs, isCollapsed);
     }
 
     /**
-     * Get the snapshot document list collapsed or uncollapsed state in preferences.
-     * @return {@code True} Whether the snapshot documnets list is collapsed.
+     * Gets whether the list of snapshot documents is collapsed (vs expanded) on
+     * the Recent Tabs page.
+     * @return Whether the list of snapshot documents is collapsed (vs expanded) on
+     *         the Recent Tabs page.
      */
     public boolean getSnapshotDocumentCollapsed() {
         return nativeGetSnapshotDocumentCollapsed(mNativeNewTabPagePrefs);
     }
 
     /**
-     * Set recently closed tabs list collapsed or uncollapsed state in preferences.
-     * @param isCollapsed {@code True} Whether we want the recently closed tabs list to be
-     * collapsed.
+     * Sets whether the list of recently closed tabs is collapsed (vs expanded) on the Recent Tabs
+     * page.
+     * @param isCollapsed Whether we want the recently closed tabs list to be collapsed.
      */
     public void setRecentlyClosedTabsCollapsed(boolean isCollapsed) {
         nativeSetRecentlyClosedTabsCollapsed(mNativeNewTabPagePrefs, isCollapsed);
     }
 
     /**
-     * Get the recently closed document list collapsed or uncollapsed state in preferences.
-     * @return {@code True} Whether the recently closed list is collapsed.
+     * Gets whether the list of recently closed tabs is collapsed (vs expanded) on
+     * the Recent Tabs page.
+     * @return Whether the list of recently closed tabs is collapsed (vs expanded) on
+     *         the Recent Tabs page.
      */
     public boolean getRecentlyClosedTabsCollapsed() {
         return nativeGetRecentlyClosedTabsCollapsed(mNativeNewTabPagePrefs);
     }
 
     /**
-     * Set sync promo collapsed or uncollapsed state in preferences.
-     * @param isCollapsed {@code True} Whether we want the sync promo to be collapsed.
+     * Sets whether sync promo is collapsed (vs expanded) on the Recent Tabs page.
+     * @param isCollapsed Whether we want the sync promo to be collapsed.
      */
     public void setSyncPromoCollapsed(boolean isCollapsed) {
         nativeSetSyncPromoCollapsed(mNativeNewTabPagePrefs, isCollapsed);
     }
 
     /**
-     * Get the sync promo collapsed or uncollapsed state in preferences.
-     * @return {@code True} Whether the snapshot documnets list is collapsed.
+     * Gets whether sync promo is collapsed (vs expanded) on the Recent Tabs page.
+     * @return Whether the sync promo is collapsed (vs expanded) on the Recent Tabs page.
      */
     public boolean getSyncPromoCollapsed() {
         return nativeGetSyncPromoCollapsed(mNativeNewTabPagePrefs);
     }
 
     /**
-     * Set the given session collapsed or uncollapsed in preferences.
-     * @param session     Session to set collapsed or uncollapsed.
-     * @param isCollapsed {@code True} iff we want the session to be collapsed.
+     * Sets whether the given foreign session is collapsed (vs expanded) on the Recent Tabs page.
+     * @param session Session to set collapsed or expanded.
+     * @param isCollapsed Whether we want the foreign session to be collapsed.
      */
     public void setForeignSessionCollapsed(ForeignSession session, boolean isCollapsed) {
         nativeSetForeignSessionCollapsed(mNativeNewTabPagePrefs, session.tag, isCollapsed);
     }
 
     /**
-     * Get the given session collapsed or uncollapsed state in preferences.
+     * Gets whether the given foreign session is collapsed (vs expanded) on the Recent Tabs page.
      * @param  session Session to fetch collapsed state.
-     * @return         {@code True} if the session is collapsed, false if expanded.
+     * @return Whether the given foreign session is collapsed (vs expanded) on the Recent Tabs page.
      */
     public boolean getForeignSessionCollapsed(ForeignSession session) {
         return nativeGetForeignSessionCollapsed(mNativeNewTabPagePrefs, session.tag);
@@ -99,6 +122,10 @@
 
     private static native long nativeInit(Profile profile);
     private static native void nativeDestroy(long nativeNewTabPagePrefs);
+    private static native void nativeSetCurrentlyOpenTabsCollapsed(
+            long nativeNewTabPagePrefs, boolean isCollapsed);
+    private static native boolean nativeGetCurrentlyOpenTabsCollapsed(
+            long nativeNewTabPagePrefs);
     private static native void nativeSetSnapshotDocumentCollapsed(
             long nativeNewTabPagePrefs, boolean isCollapsed);
     private static native boolean nativeGetSnapshotDocumentCollapsed(
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 6bf7f43..d31dcf4 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
@@ -206,7 +206,11 @@
     }
 
     private void setupImageButton(ImageButton button, final MenuItem item) {
+        // Store and recover the level of image as button.setimageDrawable
+        // resets drawable to default level.
+        int currentLevel = item.getIcon().getLevel();
         button.setImageDrawable(item.getIcon());
+        item.getIcon().setLevel(currentLevel);
         button.setContentDescription(item.getTitle());
         button.setEnabled(item.isEnabled());
         button.setFocusable(item.isEnabled());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java
index 4cf4f85..fdd246a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCheckBox.java
@@ -14,6 +14,8 @@
  * A check box used to determine if a page should always be translated.
  */
 public class TranslateCheckBox extends CheckBox implements OnCheckedChangeListener {
+    private static final int TEXT_SIZE_SP = 13;
+
     private final SubPanelListener mListener;
     private final TranslateOptions mOptions;
 
@@ -24,6 +26,8 @@
 
         setId(R.id.infobar_extra_check);
         setText(context.getString(R.string.translate_always_text, mOptions.sourceLanguage()));
+        setTextColor(context.getResources().getColor(R.color.infobar_text));
+        setTextSize(TEXT_SIZE_SP);
         setChecked(mOptions.alwaysTranslateLanguageState());
         setOnCheckedChangeListener(this);
     }
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index c1cf145..80cd0fb 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -7,7 +7,9 @@
 #include "content/public/app/content_main.h"
 
 #if defined(OS_WIN)
+#include "base/debug/dump_without_crashing.h"
 #include "base/win/win_util.h"
+#include "chrome/common/chrome_constants.h"
 
 #define DLLEXPORT __declspec(dllexport)
 
@@ -38,6 +40,15 @@
   base::win::SetAbortBehaviorForCrashReporting();
   params.instance = instance;
   params.sandbox_info = sandbox_info;
+
+  // SetDumpWithoutCrashingFunction must be passed the DumpProcess function
+  // from the EXE and not from the DLL in order for DumpWithoutCrashing to
+  // function correctly.
+  typedef void (__cdecl *DumpProcessFunction)();
+  DumpProcessFunction DumpProcess = reinterpret_cast<DumpProcessFunction>(
+      ::GetProcAddress(::GetModuleHandle(chrome::kBrowserProcessExecutableName),
+          "DumpProcessWithoutCrash"));
+  base::debug::SetDumpWithoutCrashingFunction(DumpProcess);
 #else
   params.argc = argc;
   params.argv = argv;
diff --git a/chrome/browser/android/new_tab_page_prefs.cc b/chrome/browser/android/new_tab_page_prefs.cc
index 0358fb0..616beb0 100644
--- a/chrome/browser/android/new_tab_page_prefs.cc
+++ b/chrome/browser/android/new_tab_page_prefs.cc
@@ -33,6 +33,19 @@
 NewTabPagePrefs::~NewTabPagePrefs() {
 }
 
+jboolean NewTabPagePrefs::GetCurrentlyOpenTabsCollapsed(JNIEnv* env,
+                                                       jobject obj) {
+  PrefService* prefs = profile_->GetPrefs();
+  return prefs->GetBoolean(prefs::kNtpCollapsedCurrentlyOpenTabs);
+}
+
+void NewTabPagePrefs::SetCurrentlyOpenTabsCollapsed(JNIEnv* env,
+                                                   jobject obj,
+                                                   jboolean is_collapsed) {
+  PrefService* prefs = profile_->GetPrefs();
+  prefs->SetBoolean(prefs::kNtpCollapsedCurrentlyOpenTabs, is_collapsed);
+}
+
 jboolean NewTabPagePrefs::GetSnapshotDocumentCollapsed(JNIEnv* env,
                                                        jobject obj) {
   return profile_->GetPrefs()->GetBoolean(prefs::kNtpCollapsedSnapshotDocument);
@@ -96,6 +109,10 @@
 void NewTabPagePrefs::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
   registry->RegisterBooleanPref(
+      prefs::kNtpCollapsedCurrentlyOpenTabs,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  registry->RegisterBooleanPref(
       prefs::kNtpCollapsedSnapshotDocument,
       false,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
diff --git a/chrome/browser/android/new_tab_page_prefs.h b/chrome/browser/android/new_tab_page_prefs.h
index 99b6a09..7d4333d 100644
--- a/chrome/browser/android/new_tab_page_prefs.h
+++ b/chrome/browser/android/new_tab_page_prefs.h
@@ -14,6 +14,11 @@
   explicit NewTabPagePrefs(Profile* profile);
   void Destroy(JNIEnv* env, jobject obj);
 
+  jboolean GetCurrentlyOpenTabsCollapsed(JNIEnv* env, jobject obj);
+  void SetCurrentlyOpenTabsCollapsed(JNIEnv* env,
+                                     jobject obj,
+                                     jboolean is_collapsed);
+
   jboolean GetSnapshotDocumentCollapsed(JNIEnv* env, jobject obj);
   void SetSnapshotDocumentCollapsed(JNIEnv* env,
                                     jobject obj,
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index b0260a6..03c947b 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -388,9 +388,9 @@
   RegisterRecoveryComponent(cus, g_browser_process->local_state());
   RegisterPepperFlashComponent(cus);
   RegisterSwiftShaderComponent(cus);
+  RegisterWidevineCdmComponent(cus);
   g_browser_process->pnacl_component_installer()->RegisterPnaclComponent(
       cus, command_line);
-  RegisterWidevineCdmComponent(cus);
 #endif
 
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
index ac6546f..99cda7a 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
@@ -21,22 +21,11 @@
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
-#include "components/policy/core/common/cloud/enterprise_metrics.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
 namespace chromeos {
 
-namespace {
-
-void UMA(int sample) {
-  UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment,
-                            sample,
-                            policy::kMetricEnrollmentSize);
-}
-
-}  // namespace
-
 EnrollmentScreen::EnrollmentScreen(
     ScreenObserver* observer,
     EnrollmentScreenActor* actor)
@@ -74,6 +63,7 @@
     actor_->ShowEnrollmentSpinnerScreen();
     actor_->FetchOAuthToken();
   } else {
+    UMA(policy::kMetricEnrollmentTriggered);
     actor_->ResetAuth(base::Bind(&EnrollmentScreen::ShowSigninScreen,
                                  weak_ptr_factory_.GetWeakPtr()));
   }
@@ -91,15 +81,18 @@
 void EnrollmentScreen::OnLoginDone(const std::string& user) {
   user_ = gaia::CanonicalizeEmail(user);
 
-  UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoRetried
-                           : policy::kMetricEnrollmentStarted);
+  if (is_auto_enrollment())
+    UMA(policy::kMetricEnrollmentAutoRetried);
+  else if (enrollment_failed_once_)
+    UMA(policy::kMetricEnrollmentRetried);
+  else
+    UMA(policy::kMetricEnrollmentStarted);
 
   actor_->ShowEnrollmentSpinnerScreen();
   actor_->FetchOAuthToken();
 }
 
-void EnrollmentScreen::OnAuthError(
-    const GoogleServiceAuthError& error) {
+void EnrollmentScreen::OnAuthError(const GoogleServiceAuthError& error) {
   enrollment_failed_once_ = true;
   actor_->ShowAuthError(error);
 
@@ -145,7 +138,8 @@
 }
 
 void EnrollmentScreen::OnCancel() {
-  if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED) {
+  if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED ||
+      enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
     actor_->ResetAuth(
         base::Bind(&ScreenObserver::OnExit,
                    base::Unretained(get_screen_observer()),
@@ -303,7 +297,17 @@
   UMAFailure(policy::kMetricEnrollmentOtherFailed);
 }
 
-void EnrollmentScreen::UMAFailure(int sample) {
+void EnrollmentScreen::UMA(policy::MetricEnrollment sample) {
+  if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY) {
+    UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollmentRecovery, sample,
+                              policy::kMetricEnrollmentSize);
+  } else {
+    UMA_HISTOGRAM_ENUMERATION(policy::kMetricEnrollment, sample,
+                              policy::kMetricEnrollmentSize);
+  }
+}
+
+void EnrollmentScreen::UMAFailure(policy::MetricEnrollment sample) {
   if (is_auto_enrollment())
     sample = policy::kMetricEnrollmentAutoFailed;
   UMA(sample);
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
index f88384f..0002d88 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
+#include "components/policy/core/common/cloud/enterprise_metrics.h"
 
 namespace chromeos {
 
@@ -69,10 +70,15 @@
   // operations are completed.
   void ShowEnrollmentStatusOnSuccess(const policy::EnrollmentStatus& status);
 
-  // Logs a UMA event in the kMetricEnrollment histogram. If auto-enrollment is
-  // on |sample| is ignored and a kMetricEnrollmentAutoFailed sample is logged
+  // Logs an UMA event in the kMetricEnrollment or the kMetricEnrollmentRecovery
+  // histogram, depending on |enrollment_mode_|.
+  void UMA(policy::MetricEnrollment sample);
+
+  // Logs an UMA event in the kMetricEnrollment or the kMetricEnrollmentRecovery
+  // histogram, depending on |enrollment_mode_|.  If auto-enrollment is on,
+  // |sample| is ignored and a kMetricEnrollmentAutoFailed sample is logged
   // instead.
-  void UMAFailure(int sample);
+  void UMAFailure(policy::MetricEnrollment sample);
 
   // Shows the signin screen. Used as a callback to run after auth reset.
   void ShowSigninScreen();
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
index 84a4863..74f4ffe 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
@@ -29,11 +29,14 @@
     UI_ERROR_FATAL,
   };
 
-  // Describes the enrollment mode.
+  // Describes the enrollment mode.  Must be kept in sync with
+  // |kEnrollmentModes| in enrollment_screen_handler.cc.
   enum EnrollmentMode {
-    ENROLLMENT_MODE_MANUAL,  // Manually triggered enrollment.
-    ENROLLMENT_MODE_FORCED,  // Forced enrollment, user can't skip.
-    ENROLLMENT_MODE_AUTO,    // Auto-enrollment during first sign-in.
+    ENROLLMENT_MODE_MANUAL,    // Manually triggered enrollment.
+    ENROLLMENT_MODE_FORCED,    // Forced enrollment, user can't skip.
+    ENROLLMENT_MODE_AUTO,      // Auto-enrollment during first sign-in.
+    ENROLLMENT_MODE_RECOVERY,  // Recover from "spontaneous unenrollment".
+    ENROLLMENT_MODE_COUNT      // Counter must be last. Not an enrollment mode.
   };
 
   // This defines the interface for controllers which will be called back when
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 5332ecf..94bad1c 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -54,6 +54,7 @@
 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/timezone/timezone_provider.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/options/options_util.h"
@@ -173,6 +174,7 @@
       oobe_display_(oobe_display),
       usage_statistics_reporting_(true),
       skip_update_enroll_after_eula_(false),
+      enrollment_recovery_(ShouldRecoverEnrollment()),
       login_screen_started_(false),
       user_image_screen_return_to_previous_hack_(false),
       timezone_resolved_(false),
@@ -446,15 +448,18 @@
 
   EnrollmentScreenActor::EnrollmentMode mode =
       EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
-  if (is_auto_enrollment)
-    mode = EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
-  else if (ShouldAutoStartEnrollment() && !CanExitEnrollment())
-    mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
-  else if (ShouldRecoverEnrollment())
-    mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
-
   EnrollmentScreen* screen = GetEnrollmentScreen();
-  screen->SetParameters(mode, GetForcedEnrollmentDomain(), user);
+  std::string enrollment_domain = GetForcedEnrollmentDomain();
+  if (is_auto_enrollment) {
+    mode = EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
+  } else if (enrollment_recovery_) {
+    mode = EnrollmentScreenActor::ENROLLMENT_MODE_RECOVERY;
+    enrollment_domain = GetEnrollmentRecoveryDomain();
+  } else if (ShouldAutoStartEnrollment() && !CanExitEnrollment()) {
+    mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
+  }
+
+  screen->SetParameters(mode, enrollment_domain, user);
   SetCurrentScreen(screen);
 }
 
@@ -654,7 +659,7 @@
 void WizardController::OnEnrollmentDone() {
   // Mark OOBE as completed only if enterprise enrollment was part of the
   // forced flow (i.e. app kiosk).
-  if (ShouldAutoStartEnrollment() || ShouldRecoverEnrollment())
+  if (ShouldAutoStartEnrollment() || enrollment_recovery_)
     PerformOOBECompletedActions();
 
   // TODO(mnissler): Unify the logic for auto-login for Public Sessions and
@@ -699,7 +704,7 @@
 }
 
 void WizardController::OnOOBECompleted() {
-  if (ShouldAutoStartEnrollment() || ShouldRecoverEnrollment()) {
+  if (ShouldAutoStartEnrollment() || enrollment_recovery_) {
     ShowEnrollmentScreen();
   } else {
     PerformOOBECompletedActions();
@@ -759,6 +764,9 @@
       "HIDDetection.TimesDialogShownPerOOBECompleted",
       GetLocalState()->GetInteger(prefs::kTimesHIDDialogShown));
   GetLocalState()->ClearPref(prefs::kTimesHIDDialogShown);
+
+  if (enrollment_recovery_)
+    chrome::AttemptRestart();
 }
 
 void WizardController::SetCurrentScreen(WizardScreen* new_current) {
@@ -1021,6 +1029,14 @@
 }
 
 // static
+std::string WizardController::GetEnrollmentRecoveryDomain() {
+  policy::BrowserPolicyConnectorChromeOS* connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  return
+      connector->GetDeviceCloudPolicyManager()->GetEnrollmentRecoveryDomain();
+}
+
+// static
 bool WizardController::CanExitEnrollment() {
   policy::BrowserPolicyConnectorChromeOS* connector =
       g_browser_process->platform_part()->browser_policy_connector_chromeos();
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 1194b88..f230ab5 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -94,9 +94,13 @@
   // Checks whether OOBE should start enrollment automatically.
   static bool ShouldAutoStartEnrollment();
 
-  // Checks whether OOBE should recover enrollment.
+  // Checks whether OOBE should recover enrollment.  Note that this flips to
+  // false once device policy has been restored as a part of recovery.
   static bool ShouldRecoverEnrollment();
 
+  // Obtains domain the device used to be enrolled to from install attributes.
+  static std::string GetEnrollmentRecoveryDomain();
+
   // Shows the first screen defined by |first_screen_name| or by default
   // if the parameter is empty. Takes ownership of |screen_parameters|.
   void Init(const std::string& first_screen_name,
@@ -356,6 +360,10 @@
   // EULA is accepted.
   bool skip_update_enroll_after_eula_;
 
+  // Whether enrollment will be or has been recovered in the current wizard
+  // instance.
+  bool enrollment_recovery_;
+
   // Time when the EULA was accepted. Used to measure the duration from the EULA
   // acceptance until the Sign-In screen is displayed.
   base::Time time_eula_accepted_;
diff --git a/chrome/browser/chromeos/net/network_portal_detector_strategy.cc b/chrome/browser/chromeos/net/network_portal_detector_strategy.cc
index cae7f93..f707f8a 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_strategy.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_strategy.cc
@@ -75,10 +75,14 @@
 class SessionStrategy : public PortalDetectorStrategy {
  public:
   static const int kFastDelayBetweenAttemptsSec = 1;
-  static const int kMaxFastAttempts = 3;
   static const int kFastAttemptTimeoutSec = 3;
+  static const int kMaxFastAttempts = 3;
 
-  static const int kSlowDelayBetweenAttemptsSec = 10;
+  static const int kNormalDelayBetweenAttemptsSec = 10;
+  static const int kNormalAttemptTimeoutSec = 5;
+  static const int kMaxNormalAttempts = 3;
+
+  static const int kSlowDelayBetweenAttemptsSec = 2 * 60;
   static const int kSlowAttemptTimeoutSec = 5;
 
   SessionStrategy() {}
@@ -90,22 +94,34 @@
   virtual bool CanPerformAttemptAfterDetectionImpl() OVERRIDE { return true; }
   virtual base::TimeDelta GetDelayTillNextAttemptImpl() OVERRIDE {
     int delay;
-    if (delegate_->AttemptCount() < kMaxFastAttempts)
+    if (IsFastAttempt())
       delay = kFastDelayBetweenAttemptsSec;
+    else if (IsNormalAttempt())
+      delay = kNormalDelayBetweenAttemptsSec;
     else
       delay = kSlowDelayBetweenAttemptsSec;
     return AdjustDelay(base::TimeDelta::FromSeconds(delay));
   }
   virtual base::TimeDelta GetNextAttemptTimeoutImpl() OVERRIDE {
     int timeout;
-    if (delegate_->AttemptCount() < kMaxFastAttempts)
+    if (IsFastAttempt())
       timeout = kFastAttemptTimeoutSec;
+    else if (IsNormalAttempt())
+      timeout = kNormalAttemptTimeoutSec;
     else
       timeout = kSlowAttemptTimeoutSec;
     return base::TimeDelta::FromSeconds(timeout);
   }
 
  private:
+  bool IsFastAttempt() {
+    return delegate_->AttemptCount() < kMaxFastAttempts;
+  }
+
+  bool IsNormalAttempt() {
+    return delegate_->AttemptCount() < kMaxFastAttempts + kMaxNormalAttempts;
+  }
+
   DISALLOW_COPY_AND_ASSIGN(SessionStrategy);
 };
 
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index 6da4fb2..51f55d6 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -237,6 +237,11 @@
   return false;
 }
 
+std::string
+DeviceCloudPolicyManagerChromeOS::GetEnrollmentRecoveryDomain() const {
+  return install_attributes_->GetDomain();
+}
+
 bool DeviceCloudPolicyManagerChromeOS::CanExitEnrollment() const {
   if (GetRestoreMode() == kDeviceStateRestoreModeReEnrollmentEnforced)
     return false;
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
index fffd946..76f4d25 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
@@ -86,6 +86,9 @@
   // Checks whether enterprise enrollment recovery is required.
   bool ShouldRecoverEnrollment() const;
 
+  // Looks up the domain from |install_attributes_|.
+  std::string GetEnrollmentRecoveryDomain() const;
+
   // Checks whether the user can cancel enrollment.
   bool CanExitEnrollment() const;
 
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
index 13f4992..2136a10 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
@@ -26,7 +26,7 @@
     : device_settings_service_(device_settings_service),
       install_attributes_(install_attributes),
       background_task_runner_(background_task_runner),
-      first_update_(true),
+      enrollment_validation_done_(false),
       weak_factory_(this) {
   device_settings_service_->AddObserver(this);
 }
@@ -138,32 +138,47 @@
     return;
   }
 
-  // Fill UMA histogram once per session.  Skip temp validation error because it
-  // is not a definitive result (policy load will be retried).
+  // Once per session, validate internal consistency of enrollment state (DM
+  // token must be present on enrolled devices) and in case of failure set flag
+  // to indicate that recovery is required.
   const chromeos::DeviceSettingsService::Status status =
       device_settings_service_->status();
-  if (first_update_ &&
-      status != chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR) {
-    first_update_ = false;
-    const bool has_dm_token =
-        status == chromeos::DeviceSettingsService::STORE_SUCCESS &&
-        device_settings_service_->policy_data() &&
-        device_settings_service_->policy_data()->has_request_token();
+  switch (status) {
+    case chromeos::DeviceSettingsService::STORE_SUCCESS:
+    case chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE:
+    case chromeos::DeviceSettingsService::STORE_NO_POLICY:
+    case chromeos::DeviceSettingsService::STORE_INVALID_POLICY:
+    case chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR: {
+      if (!enrollment_validation_done_) {
+        enrollment_validation_done_ = true;
+        const bool has_dm_token =
+            status == chromeos::DeviceSettingsService::STORE_SUCCESS &&
+            device_settings_service_->policy_data() &&
+            device_settings_service_->policy_data()->has_request_token();
 
-    // At the time LoginDisplayHostImpl decides whether enrollment flow is to be
-    // started, policy hasn't been read yet, so LoginDisplayHostImpl is not in a
-    // position to decide whether recovery is required.  To work around this,
-    // upon policy load on machines requiring recovery, a flag is stored in
-    // prefs which is accessed by LoginDisplayHostImpl early during (next) boot.
-    if (!has_dm_token) {
-      LOG(ERROR) << "Policy read on enrolled device yields no DM token! "
-                 << "Status: " << status << ".";
-      chromeos::StartupUtils::MarkEnrollmentRecoveryRequired();
+        // At the time LoginDisplayHostImpl decides whether enrollment flow is
+        // to be started, policy hasn't been read yet.  To work around this,
+        // once the need for recovery is detected upon policy load, a flag is
+        // stored in prefs which is accessed by LoginDisplayHostImpl early
+        // during (next) boot.
+        if (!has_dm_token) {
+          LOG(ERROR) << "Device policy read on enrolled device yields "
+                     << "no DM token! Status: " << status << ".";
+          chromeos::StartupUtils::MarkEnrollmentRecoveryRequired();
+        }
+        UMA_HISTOGRAM_BOOLEAN("Enterprise.EnrolledPolicyHasDMToken",
+                              has_dm_token);
+      }
+      break;
     }
-    UMA_HISTOGRAM_BOOLEAN("Enterprise.EnrolledPolicyHasDMToken", has_dm_token);
+    case chromeos::DeviceSettingsService::STORE_POLICY_ERROR:
+    case chromeos::DeviceSettingsService::STORE_OPERATION_FAILED:
+    case chromeos::DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
+      // Do nothing for write errors or transient read errors.
+      break;
   }
 
-  switch (device_settings_service_->status()) {
+  switch (status) {
     case chromeos::DeviceSettingsService::STORE_SUCCESS: {
       status_ = STATUS_OK;
       policy_.reset(new em::PolicyData());
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
index 327fdcf..dea0277 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h
@@ -76,9 +76,8 @@
 
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
 
-  // Run enrollment sanity check and UMA stats only upon the first policy
-  // read/update.
-  bool first_update_;
+  // Whether enterprise enrollment validation has yet been done.
+  bool enrollment_validation_done_;
 
   base::WeakPtrFactory<DeviceCloudPolicyStoreChromeOS> weak_factory_;
 
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index 94ae2b3..e479c08 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -603,8 +603,6 @@
             << ", time_since_last_checked="
             << time_since_last_checked.InSeconds() << " seconds";
 
-    ChangeItemState(item, CrxUpdateItem::kChecking);
-
     item->last_check = now;
     item->crx_urls.clear();
     item->crx_diffurls.clear();
@@ -622,6 +620,8 @@
     item->download_metrics.clear();
 
     items_to_check.push_back(item);
+
+    ChangeItemState(item, CrxUpdateItem::kChecking);
   }
 
   if (items_to_check.empty())
@@ -928,14 +928,14 @@
   }
 
   if (is_success) {
-    ChangeItemState(item, CrxUpdateItem::kUpdated);
     item->component.version = item->next_version;
     item->component.fingerprint = item->next_fp;
+    ChangeItemState(item, CrxUpdateItem::kUpdated);
   } else {
-    ChangeItemState(item, CrxUpdateItem::kNoUpdate);
     item->error_category = error_category;
     item->error_code = error;
     item->extra_code1 = extra_code;
+    ChangeItemState(item, CrxUpdateItem::kNoUpdate);
   }
 
   ping_manager_->OnUpdateComplete(item);
@@ -1006,17 +1006,23 @@
   if (!uit)
     return kError;
 
-  Status service_status = GetServiceStatus(uit->status);
-  // If the item is already in the process of being updated, there is
-  // no point in this call, so return kInProgress.
-  if (service_status == kInProgress)
-    return service_status;
-
-  // Otherwise the item was already checked a while back (or it is new),
-  // set its status to kNew to give it a slightly higher priority.
-  ChangeItemState(uit, CrxUpdateItem::kNew);
   uit->on_demand = true;
 
+  // If there is an update available for this item, then continue processing
+  // the update. This is an artifact of how update checks are done: in addition
+  // to the on-demand item, the update check may include other items as well.
+  if (uit->status != CrxUpdateItem::kCanUpdate) {
+    Status service_status = GetServiceStatus(uit->status);
+    // If the item is already in the process of being updated, there is
+    // no point in this call, so return kInProgress.
+    if (service_status == kInProgress)
+      return service_status;
+
+    // Otherwise the item was already checked a while back (or it is new),
+    // set its status to kNew to give it a slightly higher priority.
+    ChangeItemState(uit, CrxUpdateItem::kNew);
+  }
+
   // In case the current delay is long, set the timer to a shorter value
   // to get the ball rolling.
   if (timer_.IsRunning()) {
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index 1445247..5dbd3b1 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -222,7 +222,10 @@
   // true = Add to beginning of list to override any existing registrations.
   PluginService::GetInstance()->RegisterInternalPlugin(
       plugin_info.ToWebPluginInfo(), true);
+  // Tell the browser to refresh the plugin list. Then tell all renderers to
+  // update their plugin list caches.
   PluginService::GetInstance()->RefreshPlugins();
+  PluginService::GetInstance()->PurgePluginListCache(NULL, false);
 }
 
 }  // namespace
diff --git a/chrome/browser/plugins/plugin_info_message_filter.cc b/chrome/browser/plugins/plugin_info_message_filter.cc
index 2484160..50bbc75 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.cc
+++ b/chrome/browser/plugins/plugin_info_message_filter.cc
@@ -59,6 +59,29 @@
   return false;
 }
 
+#if defined(ENABLE_PEPPER_CDMS)
+
+enum PluginAvailabilityStatusForUMA {
+  PLUGIN_NOT_REGISTERED,
+  PLUGIN_AVAILABLE,
+  PLUGIN_DISABLED,
+  PLUGIN_AVAILABILITY_STATUS_MAX
+};
+
+static void SendPluginAvailabilityUMA(const std::string& mime_type,
+                                      PluginAvailabilityStatusForUMA status) {
+#if defined(WIDEVINE_CDM_AVAILABLE)
+  // Only report results for Widevine CDM.
+  if (mime_type != kWidevineCdmPluginMimeType)
+    return;
+
+  UMA_HISTOGRAM_ENUMERATION("Plugin.AvailabilityStatus.WidevineCdm",
+                            status, PLUGIN_AVAILABILITY_STATUS_MAX);
+#endif  // defined(WIDEVINE_CDM_AVAILABLE)
+}
+
+#endif  // defined(ENABLE_PEPPER_CDMS)
+
 }  // namespace
 
 PluginInfoMessageFilter::Context::Context(int render_process_id,
@@ -94,9 +117,11 @@
   IPC_BEGIN_MESSAGE_MAP(PluginInfoMessageFilter, message)
     IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_GetPluginInfo,
                                     OnGetPluginInfo)
+#if defined(ENABLE_PEPPER_CDMS)
     IPC_MESSAGE_HANDLER(
-        ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType,
-        OnIsInternalPluginRegisteredForMimeType)
+        ChromeViewHostMsg_IsInternalPluginAvailableForMimeType,
+        OnIsInternalPluginAvailableForMimeType)
+#endif
     IPC_MESSAGE_UNHANDLED(return false)
   IPC_END_MESSAGE_MAP()
   return true;
@@ -164,29 +189,43 @@
   Send(reply_msg);
 }
 
-void PluginInfoMessageFilter::OnIsInternalPluginRegisteredForMimeType(
+#if defined(ENABLE_PEPPER_CDMS)
+void PluginInfoMessageFilter::OnIsInternalPluginAvailableForMimeType(
     const std::string& mime_type,
-    bool* is_registered,
+    bool* is_available,
     std::vector<base::string16>* additional_param_names,
     std::vector<base::string16>* additional_param_values) {
   std::vector<WebPluginInfo> plugins;
   PluginService::GetInstance()->GetInternalPlugins(&plugins);
+
+  bool is_plugin_disabled = false;
   for (size_t i = 0; i < plugins.size(); ++i) {
+    const WebPluginInfo& plugin = plugins[i];
     const std::vector<content::WebPluginMimeType>& mime_types =
-        plugins[i].mime_types;
+        plugin.mime_types;
     for (size_t j = 0; j < mime_types.size(); ++j) {
       if (mime_types[j].mime_type == mime_type) {
-        *is_registered = true;
+        if (!context_.IsPluginEnabled(plugin)) {
+          is_plugin_disabled = true;
+          break;
+        }
+
+        *is_available = true;
         *additional_param_names = mime_types[j].additional_param_names;
         *additional_param_values = mime_types[j].additional_param_values;
+        SendPluginAvailabilityUMA(mime_type, PLUGIN_AVAILABLE);
         return;
       }
     }
   }
 
-  *is_registered = false;
+  *is_available = false;
+  SendPluginAvailabilityUMA(
+      mime_type, is_plugin_disabled ? PLUGIN_DISABLED : PLUGIN_NOT_REGISTERED);
 }
 
+#endif // defined(ENABLE_PEPPER_CDMS)
+
 void PluginInfoMessageFilter::Context::DecidePluginStatus(
     const GetPluginInfo_Params& params,
     const WebPluginInfo& plugin,
@@ -394,3 +433,7 @@
   }
 }
 
+bool PluginInfoMessageFilter::Context::IsPluginEnabled(
+    const content::WebPluginInfo& plugin) const {
+  return plugin_prefs_->IsPluginEnabled(plugin);
+}
diff --git a/chrome/browser/plugins/plugin_info_message_filter.h b/chrome/browser/plugins/plugin_info_message_filter.h
index eb8dcb9..bcedfc3 100644
--- a/chrome/browser/plugins/plugin_info_message_filter.h
+++ b/chrome/browser/plugins/plugin_info_message_filter.h
@@ -63,6 +63,7 @@
                                  bool* is_managed) const;
     void MaybeGrantAccess(const ChromeViewHostMsg_GetPluginInfo_Status& status,
                           const base::FilePath& path) const;
+    bool IsPluginEnabled(const content::WebPluginInfo& plugin) const;
 
    private:
     int render_process_id_;
@@ -99,17 +100,20 @@
                      IPC::Message* reply_msg,
                      const std::vector<content::WebPluginInfo>& plugins);
 
-  // Returns whether any internal plugin supporting |mime_type| is registered.
-  // Does not determine whether the plugin can actually be instantiated
-  // (e.g. whether it is allowed or has all its dependencies).
-  // When the returned *|is_registered| is true, |additional_param_names| and
+#if defined(ENABLE_PEPPER_CDMS)
+  // Returns whether any internal plugin supporting |mime_type| is registered
+  // and enabled. Does not determine whether the plugin can actually be
+  // instantiated (e.g. whether it has all its dependencies).
+  // When the returned *|is_available| is true, |additional_param_names| and
   // |additional_param_values| contain the name-value pairs, if any, specified
-  // for the *first* plugin found that is registered for |mime_type|.
-  void OnIsInternalPluginRegisteredForMimeType(
+  // for the *first* non-disabled plugin found that is registered for
+  // |mime_type|.
+  void OnIsInternalPluginAvailableForMimeType(
       const std::string& mime_type,
-      bool* is_registered,
+      bool* is_available,
       std::vector<base::string16>* additional_param_names,
       std::vector<base::string16>* additional_param_values);
+#endif
 
   Context context_;
 
diff --git a/chrome/browser/prefs/DEPS b/chrome/browser/prefs/DEPS
new file mode 100644
index 0000000..10b39f7
--- /dev/null
+++ b/chrome/browser/prefs/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+sync/internal_api/public/base/model_type.h",
+]
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index 25b9dc5..17f77a4 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/default_search_manager.h"
 #include "chrome/browser/search_engines/default_search_pref_migration.h"
+#include "chrome/browser/sync/glue/sync_start_util.h"
 #include "chrome/browser/ui/profile_error_dialog.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
@@ -46,6 +47,7 @@
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
+#include "sync/internal_api/public/base/model_type.h"
 #include "ui/base/resource/resource_bundle.h"
 
 #if defined(ENABLE_CONFIGURATION_POLICY)
@@ -442,16 +444,28 @@
     const scoped_refptr<user_prefs::PrefRegistrySyncable>& pref_registry,
     bool async) {
   TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
+
+  // A StartSyncFlare used to kick sync early in case of a reset event. This is
+  // done since sync may bring back the user's server value post-reset which
+  // could potentially cause a "settings flash" between the factory default and
+  // the re-instantiated server value. Starting sync ASAP minimizes the window
+  // before the server value is re-instantiated (this window can otherwise be
+  // as long as 10 seconds by default).
+  const base::Closure start_sync_flare_for_prefs =
+      base::Bind(sync_start_util::GetFlareForSyncableService(profile_path),
+                 syncer::PREFERENCES);
+
   PrefServiceSyncableFactory factory;
-  PrepareFactory(
-      &factory,
-      policy_service,
-      supervised_user_settings,
-      scoped_refptr<PersistentPrefStore>(
-          CreateProfilePrefStoreManager(profile_path)->CreateProfilePrefStore(
-              pref_io_task_runner, validation_delegate)),
-      extension_prefs,
-      async);
+  PrepareFactory(&factory,
+                 policy_service,
+                 supervised_user_settings,
+                 scoped_refptr<PersistentPrefStore>(
+                     CreateProfilePrefStoreManager(profile_path)
+                         ->CreateProfilePrefStore(pref_io_task_runner,
+                                                  start_sync_flare_for_prefs,
+                                                  validation_delegate)),
+                 extension_prefs,
+                 async);
   scoped_ptr<PrefServiceSyncable> pref_service =
       factory.CreateSyncable(pref_registry.get());
 
diff --git a/chrome/browser/prefs/pref_hash_filter.cc b/chrome/browser/prefs/pref_hash_filter.cc
index 8bdf994..9c2a62e 100644
--- a/chrome/browser/prefs/pref_hash_filter.cc
+++ b/chrome/browser/prefs/pref_hash_filter.cc
@@ -24,10 +24,12 @@
 PrefHashFilter::PrefHashFilter(
     scoped_ptr<PrefHashStore> pref_hash_store,
     const std::vector<TrackedPreferenceMetadata>& tracked_preferences,
+    const base::Closure& on_reset_on_load,
     TrackedPreferenceValidationDelegate* delegate,
     size_t reporting_ids_count,
     bool report_super_mac_validity)
     : pref_hash_store_(pref_hash_store.Pass()),
+      on_reset_on_load_(on_reset_on_load),
       report_super_mac_validity_(report_super_mac_validity) {
   DCHECK(pref_hash_store_);
   DCHECK_GE(reporting_ids_count, tracked_preferences.size());
@@ -185,6 +187,9 @@
                              new base::StringValue(base::Int64ToString(
                                  base::Time::Now().ToInternalValue())));
     FilterUpdate(prefs::kPreferenceResetTime);
+
+    if (!on_reset_on_load_.is_null())
+      on_reset_on_load_.Run();
   }
 
   // TODO(gab): Remove this histogram by Feb 21 2014; after sufficient timing
diff --git a/chrome/browser/prefs/pref_hash_filter.h b/chrome/browser/prefs/pref_hash_filter.h
index f394557..f61222b 100644
--- a/chrome/browser/prefs/pref_hash_filter.h
+++ b/chrome/browser/prefs/pref_hash_filter.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "base/memory/scoped_ptr.h"
@@ -60,6 +61,8 @@
   // Constructs a PrefHashFilter tracking the specified |tracked_preferences|
   // using |pref_hash_store| to check/store hashes. An optional |delegate| is
   // notified of the status of each preference as it is checked.
+  // If |on_reset_on_load| is provided, it will be invoked if a reset occurs in
+  // FilterOnLoad.
   // |reporting_ids_count| is the count of all possible IDs (possibly greater
   // than |tracked_preferences.size()|). If |report_super_mac_validity| is true,
   // the state of the super MAC will be reported via UMA during
@@ -67,6 +70,7 @@
   PrefHashFilter(
       scoped_ptr<PrefHashStore> pref_hash_store,
       const std::vector<TrackedPreferenceMetadata>& tracked_preferences,
+      const base::Closure& on_reset_on_load,
       TrackedPreferenceValidationDelegate* delegate,
       size_t reporting_ids_count,
       bool report_super_mac_validity);
@@ -116,6 +120,9 @@
 
   scoped_ptr<PrefHashStore> pref_hash_store_;
 
+  // Invoked if a reset occurs in a call to FilterOnLoad.
+  const base::Closure on_reset_on_load_;
+
   TrackedPreferencesMap tracked_paths_;
 
   // The set of all paths whose value has changed since the last call to
diff --git a/chrome/browser/prefs/pref_hash_filter_unittest.cc b/chrome/browser/prefs/pref_hash_filter_unittest.cc
index 3b5e821..429cd5c 100644
--- a/chrome/browser/prefs/pref_hash_filter_unittest.cc
+++ b/chrome/browser/prefs/pref_hash_filter_unittest.cc
@@ -348,7 +348,8 @@
  public:
   PrefHashFilterTest() : mock_pref_hash_store_(NULL),
                          pref_store_contents_(new base::DictionaryValue),
-                         last_filter_on_load_modified_prefs_(false) {}
+                         last_filter_on_load_modified_prefs_(false),
+                         reset_recorded_(false) {}
 
   virtual void SetUp() OVERRIDE {
     // Construct a PrefHashFilter and MockPrefHashStore for the test.
@@ -364,16 +365,21 @@
     scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
         new MockPrefHashStore);
     mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
-    pref_hash_filter_.reset(
-        new PrefHashFilter(temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
-                           configuration,
-                           &mock_validation_delegate_,
-                           arraysize(kTestTrackedPrefs),
-                           true));
+    pref_hash_filter_.reset(new PrefHashFilter(
+        temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
+        configuration,
+        base::Bind(&PrefHashFilterTest::RecordReset, base::Unretained(this)),
+        &mock_validation_delegate_,
+        arraysize(kTestTrackedPrefs),
+        true));
   }
 
-  bool RecordedReset() {
-    return pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL);
+  // Verifies whether a reset was reported by the PrefHashFiler. Also verifies
+  // that kPreferenceResetTime was set (or not) accordingly.
+  void VerifyRecordedReset(bool reset_expected) {
+    EXPECT_EQ(reset_expected, reset_recorded_);
+    EXPECT_EQ(reset_expected,
+              pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL));
   }
 
   // Calls FilterOnLoad() on |pref_hash_Filter_|. |pref_store_contents_| is
@@ -404,6 +410,15 @@
     EXPECT_EQ(expected_schedule_write, schedule_write);
   }
 
+  void RecordReset() {
+    // As-is |reset_recorded_| is only designed to remember a single reset, make
+    // sure none was previously recorded.
+    EXPECT_FALSE(reset_recorded_);
+    reset_recorded_ = true;
+  }
+
+  bool reset_recorded_;
+
   DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest);
 };
 
@@ -421,7 +436,7 @@
                         kTestTrackedPrefs[i].name).first);
   }
   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
-  ASSERT_FALSE(RecordedReset());
+  VerifyRecordedReset(false);
 
   // Delegate saw all paths, and all unchanged.
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
@@ -450,7 +465,7 @@
   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second);
 
   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
-  ASSERT_FALSE(RecordedReset());
+  VerifyRecordedReset(false);
 }
 
 TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) {
@@ -474,7 +489,7 @@
   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second);
 
   ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
-  ASSERT_FALSE(RecordedReset());
+  VerifyRecordedReset(false);
 }
 
 TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) {
@@ -644,7 +659,7 @@
     ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL));
     ASSERT_EQ(NULL, stored_split_value.first);
 
-    ASSERT_TRUE(RecordedReset());
+    VerifyRecordedReset(true);
   } else {
     // Otherwise the values should have remained intact and the hashes should
     // have been updated to match them.
@@ -658,7 +673,7 @@
     ASSERT_EQ(dict_value, split_value_in_store);
     ASSERT_EQ(dict_value, stored_split_value.first);
 
-    ASSERT_FALSE(RecordedReset());
+    VerifyRecordedReset(false);
   }
 }
 
@@ -771,7 +786,7 @@
     ASSERT_TRUE(dict_value->HasKey("d"));
     ASSERT_EQ(dict_value, stored_split_value.first);
 
-    ASSERT_TRUE(RecordedReset());
+    VerifyRecordedReset(true);
   } else {
     // Otherwise the value should have remained intact and the hash should have
     // been updated to match it.
@@ -790,7 +805,7 @@
     ASSERT_TRUE(dict_value->HasKey("d"));
     ASSERT_EQ(dict_value, stored_split_value.first);
 
-    ASSERT_FALSE(RecordedReset());
+    VerifyRecordedReset(false);
   }
 }
 
@@ -873,7 +888,7 @@
     ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL));
     ASSERT_EQ(NULL, stored_atomic_value.first);
 
-    ASSERT_TRUE(RecordedReset());
+    VerifyRecordedReset(true);
   } else {
     // Otherwise the value should have remained intact and the hash should have
     // been updated to match it.
@@ -882,7 +897,7 @@
     ASSERT_EQ(list_value, atomic_value_in_store);
     ASSERT_EQ(list_value, stored_atomic_value.first);
 
-    ASSERT_FALSE(RecordedReset());
+    VerifyRecordedReset(false);
   }
 }
 
@@ -942,7 +957,7 @@
   ASSERT_EQ(dict_value, split_value_in_store);
   ASSERT_EQ(dict_value, stored_split_value.first);
 
-  ASSERT_FALSE(RecordedReset());
+  VerifyRecordedReset(false);
 }
 
 TEST_P(PrefHashFilterTest, DontResetReportOnly) {
@@ -1005,7 +1020,7 @@
     ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref).first);
     ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref2).first);
 
-    ASSERT_TRUE(RecordedReset());
+    VerifyRecordedReset(true);
   } else {
     const base::Value* value_in_store;
     const base::Value* value_in_store2;
@@ -1018,7 +1033,7 @@
     ASSERT_EQ(int_value2,
               mock_pref_hash_store_->stored_value(kAtomicPref2).first);
 
-    ASSERT_FALSE(RecordedReset());
+    VerifyRecordedReset(false);
   }
 }
 
diff --git a/chrome/browser/prefs/profile_pref_store_manager.cc b/chrome/browser/prefs/profile_pref_store_manager.cc
index f4264b7..f913d9a 100644
--- a/chrome/browser/prefs/profile_pref_store_manager.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/prefs/profile_pref_store_manager.h"
 
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
@@ -81,6 +82,7 @@
 
 PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore(
     const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
+    const base::Closure& on_reset_on_load,
     TrackedPreferenceValidationDelegate* validation_delegate) {
   scoped_ptr<PrefFilter> pref_filter;
   if (!kPlatformSupportsPreferenceTracking) {
@@ -111,12 +113,14 @@
   scoped_ptr<PrefHashFilter> unprotected_pref_hash_filter(
       new PrefHashFilter(GetPrefHashStore(false),
                          unprotected_configuration,
+                         base::Closure(),
                          validation_delegate,
                          reporting_ids_count_,
                          false));
   scoped_ptr<PrefHashFilter> protected_pref_hash_filter(
       new PrefHashFilter(GetPrefHashStore(true),
                          protected_configuration,
+                         on_reset_on_load,
                          validation_delegate,
                          reporting_ids_count_,
                          true));
@@ -175,6 +179,7 @@
     to_serialize = copy.get();
     PrefHashFilter(GetPrefHashStore(false),
                    tracking_configuration_,
+                   base::Closure(),
                    NULL,
                    reporting_ids_count_,
                    false).Initialize(copy.get());
@@ -209,6 +214,7 @@
     pref_filter.reset(
         new PrefHashFilter(pref_hash_store_impl.PassAs<PrefHashStore>(),
                            tracking_configuration_,
+                           base::Closure(),
                            NULL,
                            reporting_ids_count_,
                            false));
diff --git a/chrome/browser/prefs/profile_pref_store_manager.h b/chrome/browser/prefs/profile_pref_store_manager.h
index 806b129..759b988 100644
--- a/chrome/browser/prefs/profile_pref_store_manager.h
+++ b/chrome/browser/prefs/profile_pref_store_manager.h
@@ -79,10 +79,13 @@
   static void ClearResetTime(PrefService* pref_service);
 
   // Creates a PersistentPrefStore providing access to the user preferences of
-  // the managed profile. An optional |validation_delegate| will be notified
+  // the managed profile. If |on_reset| is provided, it will be invoked if a
+  // reset occurs as a result of loading the profile's prefs.
+  // An optional |validation_delegate| will be notified
   // of the status of each tracked preference as they are checked.
   PersistentPrefStore* CreateProfilePrefStore(
       const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
+      const base::Closure& on_reset_on_load,
       TrackedPreferenceValidationDelegate* validation_delegate);
 
   // Initializes the preferences for the managed profile with the preference
diff --git a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
index c478ac4..ead5ac4 100644
--- a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -92,7 +92,8 @@
                        kConfiguration + arraysize(kConfiguration)),
         profile_pref_registry_(new user_prefs::PrefRegistrySyncable),
         registry_verifier_(profile_pref_registry_),
-        seed_("seed") {}
+        seed_("seed"),
+        reset_recorded_(false) {}
 
   virtual void SetUp() OVERRIDE {
     ProfilePrefStoreManager::RegisterPrefs(local_state_.registry());
@@ -142,17 +143,25 @@
   virtual void TearDown() OVERRIDE { DestroyPrefStore(); }
 
  protected:
-  bool WasResetRecorded() {
+  // Verifies whether a reset was reported via the RecordReset() hook. Also
+  // verifies that GetResetTime() was set (or not) accordingly.
+  void VerifyResetRecorded(bool reset_expected) {
+    EXPECT_EQ(reset_expected, reset_recorded_);
+
     base::PrefServiceFactory pref_service_factory;
     pref_service_factory.set_user_prefs(pref_store_);
 
     scoped_ptr<PrefService> pref_service(
         pref_service_factory.Create(profile_pref_registry_));
 
-    return !ProfilePrefStoreManager::GetResetTime(pref_service.get()).is_null();
+    EXPECT_EQ(
+        reset_expected,
+        !ProfilePrefStoreManager::GetResetTime(pref_service.get()).is_null());
   }
 
   void ClearResetRecorded() {
+    reset_recorded_ = false;
+
     base::PrefServiceFactory pref_service_factory;
     pref_service_factory.set_user_prefs(pref_store_);
 
@@ -168,6 +177,8 @@
     scoped_refptr<PersistentPrefStore> pref_store =
         manager_->CreateProfilePrefStore(
             main_message_loop_.message_loop_proxy(),
+            base::Bind(&ProfilePrefStoreManagerTest::RecordReset,
+                       base::Unretained(this)),
             &mock_validation_delegate_);
     InitializePrefStore(pref_store);
     pref_store = NULL;
@@ -214,7 +225,10 @@
   void LoadExistingPrefs() {
     DestroyPrefStore();
     pref_store_ = manager_->CreateProfilePrefStore(
-        main_message_loop_.message_loop_proxy(), NULL);
+        main_message_loop_.message_loop_proxy(),
+        base::Bind(&ProfilePrefStoreManagerTest::RecordReset,
+                   base::Unretained(this)),
+        NULL);
     pref_store_->AddObserver(&registry_verifier_);
     pref_store_->ReadPrefs();
   }
@@ -267,6 +281,17 @@
   scoped_refptr<PersistentPrefStore> pref_store_;
 
   std::string seed_;
+
+ private:
+  void RecordReset() {
+    // As-is |reset_recorded_| is only designed to remember a single reset, make
+    // sure none was previously recorded (or that ClearResetRecorded() was
+    // called).
+    EXPECT_FALSE(reset_recorded_);
+    reset_recorded_ = true;
+  }
+
+  bool reset_recorded_;
 };
 
 TEST_F(ProfilePrefStoreManagerTest, StoreValues) {
@@ -276,7 +301,7 @@
 
   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
   ExpectValidationObserved(kTrackedAtomic);
   ExpectValidationObserved(kProtectedAtomic);
 }
@@ -309,8 +334,8 @@
   // will be discarded at load time, leaving this preference undefined.
   EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
             pref_store_->GetValue(kProtectedAtomic, NULL));
-  EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
-            WasResetRecorded());
+  VerifyResetRecorded(
+      ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
 
   ExpectValidationObserved(kTrackedAtomic);
   ExpectValidationObserved(kProtectedAtomic);
@@ -337,7 +362,7 @@
 
   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 
   LoadExistingPrefs();
 
@@ -347,7 +372,7 @@
 
   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 }
 
 TEST_F(ProfilePrefStoreManagerTest, MigrateWithTampering) {
@@ -380,8 +405,8 @@
   // will be discarded at load time, leaving this preference undefined.
   EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
             pref_store_->GetValue(kProtectedAtomic, NULL));
-  EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
-            WasResetRecorded());
+  VerifyResetRecorded(
+      ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
 
   LoadExistingPrefs();
 
@@ -390,7 +415,7 @@
       PrefServiceHashStoreContents::kProfilePreferenceHashes));
 
   ExpectStringValueEquals(kTrackedAtomic, kBarfoo);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 }
 
 TEST_F(ProfilePrefStoreManagerTest, InitializePrefsFromMasterPrefs) {
@@ -405,7 +430,7 @@
   // necessary to authenticate these values.
   ExpectStringValueEquals(kTrackedAtomic, kFoobar);
   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 }
 
 TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtected) {
@@ -439,7 +464,7 @@
   // Since there was a valid super MAC we were able to extend the existing trust
   // to the newly protected preference.
   ExpectStringValueEquals(kUnprotectedPref, kBarfoo);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 
   // Ensure everything is written out to disk.
   DestroyPrefStore();
@@ -450,8 +475,8 @@
   LoadExistingPrefs();
   EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
             pref_store_->GetValue(kUnprotectedPref, NULL));
-  EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
-            WasResetRecorded());
+  VerifyResetRecorded(
+      ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
 }
 
 TEST_F(ProfilePrefStoreManagerTest, NewPrefWhenFirstProtecting) {
@@ -490,7 +515,7 @@
   // Since there was a valid super MAC we were able to extend the existing trust
   // to the newly tracked & protected preference.
   ExpectStringValueEquals(kUnprotectedPref, kFoobar);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 }
 
 TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtectedWithoutTrust) {
@@ -514,8 +539,8 @@
   // discarded because new values are not accepted without a valid super MAC.
   EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
             pref_store_->GetValue(kUnprotectedPref, NULL));
-  EXPECT_EQ(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
-            WasResetRecorded());
+  VerifyResetRecorded(
+      ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
 }
 
 // This test verifies that preference values are correctly maintained when a
@@ -545,7 +570,7 @@
 
   // Verify that the value was not reset.
   ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 
   // Accessing the value of the previously protected pref didn't trigger its
   // move to the unprotected preferences file, though the loading of the pref
@@ -558,5 +583,5 @@
   pref_store_->SetValue(kProtectedAtomic, new base::StringValue(kGoodbyeWorld));
   LoadExistingPrefs();
   ExpectStringValueEquals(kProtectedAtomic, kGoodbyeWorld);
-  EXPECT_FALSE(WasResetRecorded());
+  VerifyResetRecorded(false);
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
index 1a60f6a..38c464e 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
@@ -77,7 +77,8 @@
 }
 
 #oauth-enrollment.mode-manual #oauth-enroll-learn-more-link,
-#oauth-enrollment.mode-forced #oauth-enroll-learn-more-link {
+#oauth-enrollment.mode-forced #oauth-enroll-learn-more-link,
+#oauth-enrollment.mode-recovery #oauth-enroll-learn-more-link {
   display: inline;
 }
 
@@ -132,12 +133,15 @@
 }
 
 .oauth-enroll-state-signin.mode-manual #oauth-enroll-cancel-button,
-.oauth-enroll-state-working.mode-manual #oauth-enroll-cancel-button,
 .oauth-enroll-state-signin.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-signin.mode-recovery #oauth-enroll-back-button,
+.oauth-enroll-state-working.mode-manual #oauth-enroll-cancel-button,
 .oauth-enroll-state-working.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-working.mode-recovery #oauth-enroll-back-button,
 .oauth-enroll-state-error.mode-manual #oauth-enroll-cancel-button,
 .oauth-enroll-state-error.mode-auto #oauth-enroll-retry-button,
 .oauth-enroll-state-error.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-error.mode-recovery #oauth-enroll-back-button,
 .oauth-enroll-state-explain #oauth-enroll-explain-retry-button,
 .oauth-enroll-state-success #oauth-enroll-done-button {
   display: inline;
diff --git a/chrome/browser/resources/components.html b/chrome/browser/resources/components.html
index de5e9c6..b7dfded 100644
--- a/chrome/browser/resources/components.html
+++ b/chrome/browser/resources/components.html
@@ -47,7 +47,8 @@
                 </span>
                 <span>
                   - <span i18n-content="componentVersion"></span>
-                    <span dir="ltr" jscontent="version"></span>
+                    <span dir="ltr" jscontent="version"
+                        jsvalues=".id: 'version-' + id"></span>
                 </span>
               </div>
             </div>
diff --git a/chrome/browser/resources/components.js b/chrome/browser/resources/components.js
index 036fe5b..64b6e3a 100644
--- a/chrome/browser/resources/components.js
+++ b/chrome/browser/resources/components.js
@@ -86,6 +86,9 @@
     var id = eventArgs['id'];
     $('status-' + id).textContent = eventArgs['event'];
   }
+  if (eventArgs['version']) {
+    $('version-' + id).textContent = eventArgs['version'];
+  }
 }
 
 /**
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js
index afde3e0..e99c942 100644
--- a/chrome/browser/resources/omnibox/omnibox.js
+++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -203,8 +203,8 @@
   }
 
   /**
-   * @param {Object} autocompleteSuggestion the particular autocomplete
-   *     suggestion we're in the process of displaying.
+   * @param {AutocompleteMatchMojo} autocompleteSuggestion the particular
+   *     autocomplete suggestion we're in the process of displaying.
    * @param {string} propertyName the particular property of the autocomplete
    *     suggestion that should go in this cell.
    * @return {HTMLTableCellElement} that contains the value within this
@@ -382,7 +382,8 @@
       // Javascript?  In any case, we want to display them.)
       if (inDetailedMode) {
         for (var key in autocompleteSuggestion) {
-          if (!displayedProperties[key]) {
+          if (!displayedProperties[key] &&
+              typeof autocompleteSuggestion[key] != 'function') {
             var cell = document.createElement('td');
             cell.textContent = key + '=' + autocompleteSuggestion[key];
             row.appendChild(cell);
diff --git a/chrome/browser/safe_browsing/last_download_finder.cc b/chrome/browser/safe_browsing/last_download_finder.cc
index 05e7c42..d0e1c2f 100644
--- a/chrome/browser/safe_browsing/last_download_finder.cc
+++ b/chrome/browser/safe_browsing/last_download_finder.cc
@@ -145,6 +145,14 @@
     return;
   }
 
+  // Exit early if already processing this profile. This could happen if, for
+  // example, NOTIFICATION_PROFILE_ADDED arrives after construction while
+  // waiting for NOTIFICATION_HISTORY_LOADED.
+  if (std::find(profiles_.begin(), profiles_.end(), profile) !=
+      profiles_.end()) {
+    return;
+  }
+
   HistoryService* history_service =
       HistoryServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS);
   // No history service is returned for profiles that do not save history.
diff --git a/chrome/browser/speech/tts_message_filter.cc b/chrome/browser/speech/tts_message_filter.cc
index 789eac3..3c47074 100644
--- a/chrome/browser/speech/tts_message_filter.cc
+++ b/chrome/browser/speech/tts_message_filter.cc
@@ -54,6 +54,10 @@
       base::Bind(&TtsMessageFilter::OnChannelClosingInUIThread, this));
 }
 
+void TtsMessageFilter::OnDestruct() const {
+  BrowserThread::DeleteOnUIThread::Destruct(this);
+}
+
 void TtsMessageFilter::OnInitializeVoiceList() {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   TtsController* tts_controller = TtsController::GetInstance();
@@ -159,4 +163,6 @@
 }
 
 TtsMessageFilter::~TtsMessageFilter() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
 }
diff --git a/chrome/browser/speech/tts_message_filter.h b/chrome/browser/speech/tts_message_filter.h
index 629745c..154f482 100644
--- a/chrome/browser/speech/tts_message_filter.h
+++ b/chrome/browser/speech/tts_message_filter.h
@@ -26,6 +26,7 @@
       content::BrowserThread::ID* thread) OVERRIDE;
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
   virtual void OnChannelClosing() OVERRIDE;
+  virtual void OnDestruct() const OVERRIDE;
 
   // UtteranceEventDelegate implementation.
   virtual void OnTtsEvent(Utterance* utterance,
@@ -37,6 +38,9 @@
   virtual void OnVoicesChanged() OVERRIDE;
 
  private:
+  friend class content::BrowserThread;
+  friend class base::DeleteHelper<TtsMessageFilter>;
+
   virtual ~TtsMessageFilter();
 
   void OnInitializeVoiceList();
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 39ef4ca..e5651d7 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
 #include "chrome/browser/net/chrome_cookie_notification_details.h"
+#include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/services/gcm/gcm_profile_service.h"
@@ -521,11 +522,20 @@
   if (backend_mode_ == SYNC)
     return !HasSyncSetupCompleted();
 
-  // Start fresh if it's the first time backup after user stopped syncing.
-  // This is needed because backup DB may contain items deleted by user during
-  // sync period and can cause back-from-dead issues.
-  if (backend_mode_ == BACKUP && !sync_prefs_.GetFirstSyncTime().is_null())
-    return true;
+  if (backend_mode_ == BACKUP) {
+    base::Time reset_time = chrome_prefs::GetResetTime(profile_);
+
+    // Start fresh if:
+    // * It's the first time backup after user stopped syncing because backup
+    //   DB may contain items deleted by user during sync period and can cause
+    //   back-from-dead issues if user didn't choose rollback.
+    // * Settings are reset during startup because of tampering to avoid
+    //   restoring settings from backup.
+    if (!sync_prefs_.GetFirstSyncTime().is_null() ||
+        (!reset_time.is_null() && profile_->GetStartTime() <= reset_time)) {
+      return true;
+    }
+  }
 
   return false;
 }
@@ -2578,3 +2588,10 @@
   }
   return result;
 }
+
+void ProfileSyncService::StartStopBackupForTesting() {
+  if (backend_mode_ == BACKUP)
+    ShutdownImpl(browser_sync::SyncBackendHost::STOP_AND_CLAIM_THREAD);
+  else
+    backup_rollback_controller_.Start(base::TimeDelta());
+}
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 0325d0d..417582a 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -780,6 +780,8 @@
   // Return the base URL of the Sync Server.
   static GURL GetSyncServiceURL(const base::CommandLine& command_line);
 
+  void StartStopBackupForTesting();
+
  protected:
   // Helper to configure the priority data types.
   void ConfigurePriorityDataTypes();
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index 2c70744..c9224e8 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/invalidation/fake_invalidation_service.h"
@@ -491,10 +492,6 @@
 }
 
 #if defined(ENABLE_PRE_SYNC_BACKUP)
-void QuitLoop() {
-  base::MessageLoop::current()->Quit();
-}
-
 TEST_F(ProfileSyncServiceTest, StartBackup) {
   CreateServiceWithoutSignIn();
   ExpectDataTypeManagerCreation(1);
@@ -502,10 +499,11 @@
   ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param);
   Initialize();
   EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
+  base::RunLoop run_loop;
   base::MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,  base::Bind(&QuitLoop),
+      FROM_HERE, run_loop.QuitClosure(),
       base::TimeDelta::FromMilliseconds(100));
-  base::MessageLoop::current()->Run();
+  run_loop.Run();
   EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
 
   EXPECT_EQ(1u, delete_dir_param.size());
@@ -520,7 +518,6 @@
   ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param);
   IssueTestTokens();
   Initialize();
-  base::MessageLoop::current()->PostTask(FROM_HERE,  base::Bind(&QuitLoop));
   EXPECT_TRUE(service()->sync_initialized());
   EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
 
@@ -555,7 +552,6 @@
   ExpectSyncBackendHostCreationCollectDeleteDir(3, &delete_dir_param);
   IssueTestTokens();
   Initialize();
-  base::MessageLoop::current()->PostTask(FROM_HERE,  base::Bind(&QuitLoop));
   EXPECT_TRUE(service()->sync_initialized());
   EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
 
@@ -586,6 +582,32 @@
   EXPECT_FALSE(delete_dir_param[1]);
   EXPECT_TRUE(delete_dir_param[2]);
 }
+
+TEST_F(ProfileSyncServiceTest, StartNewBackupDbOnSettingsReset) {
+  CreateServiceWithoutSignIn();
+  ExpectDataTypeManagerCreation(1);
+  std::vector<bool> delete_dir_param;
+  ExpectSyncBackendHostCreationCollectDeleteDir(1, &delete_dir_param);
+  Initialize();
+  EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
+
+  // Set reset time to pretend settings reset happened.
+  profile()->GetPrefs()->SetString(
+      prefs::kPreferenceResetTime,
+      base::Int64ToString(base::Time::Now().ToInternalValue()));
+
+  base::RunLoop run_loop;
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE, run_loop.QuitClosure(),
+      base::TimeDelta::FromMilliseconds(100));
+  run_loop.Run();
+
+  EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
+
+  EXPECT_EQ(1u, delete_dir_param.size());
+  EXPECT_TRUE(delete_dir_param[0]);
+}
+
 #endif
 
 TEST_F(ProfileSyncServiceTest, GetSyncServiceURL) {
diff --git a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
index 5dec3a1..bf74892 100644
--- a/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_backup_rollback_test.cc
@@ -4,12 +4,15 @@
 
 #include "base/command_line.h"
 #include "base/message_loop/message_loop.h"
+#include "base/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
+#include "chrome/browser/sync/test/integration/preferences_helper.h"
 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "sync/test/fake_server/fake_server_verifier.h"
 
@@ -21,15 +24,25 @@
 using bookmarks_helper::Remove;
 using sync_integration_test_util::AwaitCommitActivityCompletion;
 
+namespace {
+const char kUrl1[] = "http://www.google.com";
+const char kUrl2[] = "http://map.google.com";
+const char kUrl3[] = "http://plus.google.com";
+}  // anonymous namespace
+
 class SingleClientBackupRollbackTest : public SyncTest {
  public:
   SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {}
   virtual ~SingleClientBackupRollbackTest() {}
 
-  virtual void SetUp() OVERRIDE {
+  void DisableBackup() {
+    CommandLine::ForCurrentProcess()->AppendSwitch(
+          switches::kSyncDisableBackup);
+  }
+
+  void EnableRollback() {
     CommandLine::ForCurrentProcess()->AppendSwitch(
           switches::kSyncEnableRollback);
-    SyncTest::SetUp();
   }
 
  private:
@@ -41,9 +54,10 @@
   explicit BackupModeChecker(ProfileSyncService* service,
                              base::TimeDelta timeout)
       : pss_(service),
-        expiration_(base::TimeTicks::Now() + timeout) {}
+        timeout_(timeout) {}
 
   bool Wait() {
+    expiration_ = base::TimeTicks::Now() + timeout_;
     base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&BackupModeChecker::PeriodicCheck, base::Unretained(this)),
@@ -70,6 +84,7 @@
   }
 
   ProfileSyncService* pss_;
+  base::TimeDelta timeout_;
   base::TimeTicks expiration_;
 };
 
@@ -80,6 +95,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
                        MAYBE_TestBackupRollback) {
+  EnableRollback();
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
 
   // Starting state:
@@ -131,3 +147,126 @@
   const BookmarkNode* url2 = tier1_b->GetChild(0);
   ASSERT_EQ(GURL("http://www.nhl.com"), url2->url());
 }
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+#define MAYBE_TestPrefBackupRollback TestPrefBackupRollback
+#else
+#define MAYBE_TestPrefBackupRollback DISABLED_TestPrefBackupRollback
+#endif
+// Verify local preferences are not affected by preferences in backup DB under
+// backup mode.
+IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
+                       MAYBE_TestPrefBackupRollback) {
+  EnableRollback();
+
+  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+  preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl1);
+
+  BackupModeChecker checker(GetSyncService(0),
+                            base::TimeDelta::FromSeconds(15));
+  ASSERT_TRUE(checker.Wait());
+
+  // Shut down backup, then change preference.
+  GetSyncService(0)->StartStopBackupForTesting();
+  preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl2);
+
+  // Restart backup. Preference shouldn't change after backup starts.
+  GetSyncService(0)->StartStopBackupForTesting();
+  ASSERT_TRUE(checker.Wait());
+  ASSERT_EQ(kUrl2,
+            preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage));
+
+  // Start sync and change preference.
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+  preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl3);
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
+  ASSERT_TRUE(ModelMatchesVerifier(0));
+
+  // Let server return rollback command on next sync request.
+  GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
+
+  // Make another change to trigger downloading of rollback command.
+  preferences_helper::ChangeStringPref(0, prefs::kHomePage, "");
+
+  // Wait for sync to switch to backup mode after finishing rollback.
+  ASSERT_TRUE(checker.Wait());
+
+  // Verify preference is restored.
+  ASSERT_EQ(kUrl2,
+            preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage));
+}
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+#define MAYBE_RollbackNoBackup RollbackNoBackup
+#else
+#define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup
+#endif
+IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
+                       MAYBE_RollbackNoBackup) {
+  EnableRollback();
+
+  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+  // Setup sync, wait for its completion, and make sure changes were synced.
+  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
+
+  // Starting state:
+  // other_node
+  //    -> http://mail.google.com  "url0"
+  //    -> http://www.nhl.com "url1"
+  ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
+                     GURL("http://mail.google.com")));
+  ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
+                     GURL("http://www.nhl.com")));
+
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
+  ASSERT_TRUE(ModelMatchesVerifier(0));
+
+  // Let server to return rollback command on next sync request.
+  GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
+
+  // Make another change to trigger downloading of rollback command.
+  Remove(0, GetOtherNode(0), 0);
+
+  // Wait for sync to switch to backup mode after finishing rollback.
+  BackupModeChecker checker(GetSyncService(0),
+                            base::TimeDelta::FromSeconds(15));
+  ASSERT_TRUE(checker.Wait());
+
+  // Without backup DB, bookmarks added during sync shouldn't be removed.
+  ASSERT_EQ(1, GetOtherNode(0)->child_count());
+  ASSERT_EQ(GURL("http://www.nhl.com"),
+            GetOtherNode(0)->GetChild(0)->url());
+}
+
+#if defined(ENABLE_PRE_SYNC_BACKUP)
+#define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering
+#else
+#define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering
+#endif
+IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
+                       MAYBE_DontChangeBookmarkOrdering) {
+  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
+
+  const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test");
+  ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1)));
+  ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2)));
+  ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3)));
+
+  BackupModeChecker checker(GetSyncService(0),
+                            base::TimeDelta::FromSeconds(15));
+  ASSERT_TRUE(checker.Wait());
+
+  // Restart backup.
+  GetSyncService(0)->StartStopBackupForTesting();
+  GetSyncService(0)->StartStopBackupForTesting();
+  ASSERT_TRUE(checker.Wait());
+
+  // Verify bookmarks are unchanged.
+  ASSERT_EQ(3, sub_folder->child_count());
+  ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url());
+  ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url());
+  ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url());
+}
+
diff --git a/chrome/browser/ui/browser_tabrestore.cc b/chrome/browser/ui/browser_tabrestore.cc
index abe591c..c5af58f 100644
--- a/chrome/browser/ui/browser_tabrestore.cc
+++ b/chrome/browser/ui/browser_tabrestore.cc
@@ -122,8 +122,12 @@
     // location calculations to be incorrect even after a new layout with
     // proper view dimensions. TabStripModel::AddWebContents() contains similar
     // logic.
-    apps::ResizeWebContents(web_contents,
-                            browser->window()->GetRestoredBounds().size());
+    gfx::Size size = browser->window()->GetBounds().size();
+    // Fallback to the restore bounds if it's empty as the window is not shown
+    // yet and the bounds may not be available on all platforms.
+    if (size.IsEmpty())
+      size = browser->window()->GetRestoredBounds().size();
+    apps::ResizeWebContents(web_contents, size);
     web_contents->WasHidden();
   }
   SessionService* session_service =
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
index cea4db8..c896571 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
@@ -135,6 +135,7 @@
   virtual SkColor ActiveFrameColor() const OVERRIDE;
   virtual SkColor InactiveFrameColor() const OVERRIDE;
   virtual gfx::Insets GetFrameInsets() const OVERRIDE;
+  virtual bool CanHaveAlphaEnabled() const OVERRIDE;
 
   // These are used to simulate Mac-style hide/show. Since windows can be hidden
   // and shown using the app.window API, this sets is_hidden_with_app_ to
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
index 9b45321..e3bdc70 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
@@ -799,6 +799,10 @@
   return frame_rect.InsetsFrom(content_rect);
 }
 
+bool NativeAppWindowCocoa::CanHaveAlphaEnabled() const {
+  return false;
+}
+
 gfx::NativeView NativeAppWindowCocoa::GetHostView() const {
   NOTIMPLEMENTED();
   return NULL;
diff --git a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc
index a786474..a6d245b 100644
--- a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc
+++ b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.cc
@@ -154,10 +154,6 @@
   return ui::MODAL_TYPE_WINDOW;
 }
 
-ui::AXRole AppListDialogContentsView::GetAccessibleWindowRole() const {
-  return ui::AX_ROLE_DIALOG;
-}
-
 void AppListDialogContentsView::WindowClosing() {
   app_list_controller_delegate_->OnCloseChildDialog();
 }
diff --git a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h
index 51654d4..375af85 100644
--- a/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h
+++ b/chrome/browser/ui/views/app_list/app_list_dialog_contents_view.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_APP_LIST_APP_LIST_DIALOG_CONTENTS_VIEW_H_
 
 #include "ui/views/controls/button/button.h"
-#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/window/dialog_delegate.h"
 
 class AppListControllerDelegate;
 
@@ -17,7 +17,7 @@
 
 // The contents view for an App List Dialog, which covers the entire app list
 // and adds a close button.
-class AppListDialogContentsView : public views::WidgetDelegateView,
+class AppListDialogContentsView : public views::DialogDelegateView,
                                   public views::ButtonListener {
  public:
   AppListDialogContentsView(
@@ -48,7 +48,6 @@
  protected:
   // Overridden from views::WidgetDelegate:
   virtual ui::ModalType GetModalType() const OVERRIDE;
-  virtual ui::AXRole GetAccessibleWindowRole() const OVERRIDE;
   virtual void WindowClosing() OVERRIDE;
 
  private:
diff --git a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc
index b2301e6..f6a8139 100644
--- a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc
+++ b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.cc
@@ -48,6 +48,7 @@
 void AppWindowDesktopWindowTreeHostWin::HandleFrameChanged() {
   // We need to update the glass region on or off before the base class adjusts
   // the window region.
+  app_window_->OnCanHaveAlphaEnabledChanged();
   UpdateDWMFrame();
   DesktopWindowTreeHostWin::HandleFrameChanged();
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
index d16820f..2cd8f88 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
+#include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -44,22 +45,12 @@
 const char kEnrollmentStepSuccess[] = "success";
 
 // Enrollment mode strings.
-const char kEnrollmentModeManual[] = "manual";
-const char kEnrollmentModeForced[] = "forced";
-const char kEnrollmentModeAuto[] = "auto";
+const char* const kModeStrings[EnrollmentScreenActor::ENROLLMENT_MODE_COUNT] =
+    { "manual", "forced", "auto", "recovery" };
 
 std::string EnrollmentModeToString(EnrollmentScreenActor::EnrollmentMode mode) {
-  switch (mode) {
-    case EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL:
-      return kEnrollmentModeManual;
-    case EnrollmentScreenActor::ENROLLMENT_MODE_FORCED:
-      return kEnrollmentModeForced;
-    case EnrollmentScreenActor::ENROLLMENT_MODE_AUTO:
-      return kEnrollmentModeAuto;
-  }
-
-  NOTREACHED() << "Bad enrollment mode " << mode;
-  return kEnrollmentModeManual;
+  CHECK(0 <= mode && mode < EnrollmentScreenActor::ENROLLMENT_MODE_COUNT);
+  return kModeStrings[mode];
 }
 
 // A helper class that takes care of asynchronously revoking a given token.
diff --git a/chrome/browser/ui/webui/components_ui.cc b/chrome/browser/ui/webui/components_ui.cc
index c439f73..705a755 100644
--- a/chrome/browser/ui/webui/components_ui.cc
+++ b/chrome/browser/ui/webui/components_ui.cc
@@ -241,7 +241,15 @@
 void ComponentsUI::OnEvent(Events event, const std::string& id) {
   base::DictionaryValue parameters;
   parameters.SetString("event", ComponentEventToString(event));
-  if (!id.empty())
+  if (!id.empty()) {
+    using component_updater::ComponentUpdateService;
+    if (event == ComponentUpdateService::Observer::COMPONENT_UPDATED) {
+      ComponentUpdateService* cus = g_browser_process->component_updater();
+      component_updater::CrxUpdateItem item;
+      if (cus->GetComponentDetails(id, &item))
+        parameters.SetString("version", item.component.version.GetString());
+    }
     parameters.SetString("id", id);
+  }
   web_ui()->CallJavascriptFunction("onComponentEvent", parameters);
 }
diff --git a/chrome/common/extensions/api/app_current_window_internal.idl b/chrome/common/extensions/api/app_current_window_internal.idl
index a8a1cd5..890e75b 100644
--- a/chrome/common/extensions/api/app_current_window_internal.idl
+++ b/chrome/common/extensions/api/app_current_window_internal.idl
@@ -61,6 +61,7 @@
     static void onMinimized();
     static void onMaximized();
     static void onRestored();
+    static void onAlphaEnabledChanged();
     // Only sent in tests.
     static void onWindowShownForTests();
   };
diff --git a/chrome/common/extensions/api/app_window.idl b/chrome/common/extensions/api/app_window.idl
index b08037b..26922d7 100644
--- a/chrome/common/extensions/api/app_window.idl
+++ b/chrome/common/extensions/api/app_window.idl
@@ -351,6 +351,10 @@
     // <code>"alwaysOnTopWindows"</code> permission.
     static void setAlwaysOnTop(boolean alwaysOnTop);
 
+    // Can the window use alpha transparency?
+    // TODO(jackhou): Document this properly before going to stable.
+    [nodoc] static boolean alphaEnabled();
+
     // The JavaScript 'window' object for the created child.
     [instanceOf=Window] object contentWindow;
 
@@ -433,6 +437,9 @@
     // Fired when the window is restored from being minimized or maximized.
     [nocompile] static void onRestored();
 
+    // Fired when the window's ability to use alpha transparency changes.
+    [nocompile, nodoc] static void onAlphaEnabledChanged();
+
     // Event for testing. Lets tests wait until a window has been shown.
     [nocompile, nodoc] static void onWindowFirstShown();
   };
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 2885c1b..40d16c6 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1649,6 +1649,9 @@
 // Customized app page names that appear on the New Tab Page.
 const char kNtpAppPageNames[] = "ntp.app_page_names";
 
+// Keeps track of currently open tabs collapsed state in the Other Devices menu.
+const char kNtpCollapsedCurrentlyOpenTabs[] = "ntp.collapsed_open_tabs";
+
 // Keeps track of which sessions are collapsed in the Other Devices menu.
 const char kNtpCollapsedForeignSessions[] = "ntp.collapsed_foreign_sessions";
 
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 6e0a457..57f8f05 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -545,6 +545,7 @@
 extern const char kDisablePluginFinder[];
 
 extern const char kNtpAppPageNames[];
+extern const char kNtpCollapsedCurrentlyOpenTabs[];
 extern const char kNtpCollapsedForeignSessions[];
 extern const char kNtpCollapsedRecentlyClosedTabs[];
 extern const char kNtpCollapsedSnapshotDocument[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 2f58fd2..76133a8 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -444,16 +444,16 @@
                             std::string /* mime_type */,
                             ChromeViewHostMsg_GetPluginInfo_Output /* output */)
 
-// Returns whether any internal plugin supporting |mime_type| is registered
-// Does not determine whether the plugin can actually be instantiated
-// (e.g. whether it is allowed or has all its dependencies).
-// When the returned *|is_registered| is true, |additional_param_names| and
+// Returns whether any internal plugin supporting |mime_type| is registered and
+// enabled. Does not determine whether the plugin can actually be instantiated
+// (e.g. whether it has all its dependencies).
+// When the returned *|is_available| is true, |additional_param_names| and
 // |additional_param_values| contain the name-value pairs, if any, specified
-// for the *first* plugin found that is registered for |mime_type|.
+// for the *first* non-disabled plugin found that is registered for |mime_type|.
 IPC_SYNC_MESSAGE_CONTROL1_3(
-    ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType,
+    ChromeViewHostMsg_IsInternalPluginAvailableForMimeType,
     std::string /* mime_type */,
-    bool /* registered */,
+    bool /* is_available */,
     std::vector<base::string16> /* additional_param_names */,
     std::vector<base::string16> /* additional_param_values */)
 
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 8556201..49fd44b 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -655,6 +655,7 @@
 
 const char* const kChromeDebugURLs[] = {
   content::kChromeUICrashURL,
+  content::kChromeUIDumpURL,
   content::kChromeUIKillURL,
   content::kChromeUIHangURL,
   content::kChromeUIShorthangURL,
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index e8099fb..c15d493 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -32,19 +32,19 @@
 using content::SupportedCodecs;
 
 #if defined(ENABLE_PEPPER_CDMS)
-static bool IsPepperCdmRegistered(
+static bool IsPepperCdmAvailable(
     const std::string& pepper_type,
     std::vector<base::string16>* additional_param_names,
     std::vector<base::string16>* additional_param_values) {
-  bool is_registered = false;
+  bool is_available = false;
   content::RenderThread::Get()->Send(
-      new ChromeViewHostMsg_IsInternalPluginRegisteredForMimeType(
+      new ChromeViewHostMsg_IsInternalPluginAvailableForMimeType(
           pepper_type,
-          &is_registered,
+          &is_available,
           additional_param_names,
           additional_param_values));
 
-  return is_registered;
+  return is_available;
 }
 
 // External Clear Key (used for testing).
@@ -65,9 +65,9 @@
 
   std::vector<base::string16> additional_param_names;
   std::vector<base::string16> additional_param_values;
-  if (!IsPepperCdmRegistered(kExternalClearKeyPepperType,
-                             &additional_param_names,
-                             &additional_param_values)) {
+  if (!IsPepperCdmAvailable(kExternalClearKeyPepperType,
+                            &additional_param_names,
+                            &additional_param_values)) {
     return;
   }
 
@@ -141,9 +141,9 @@
 
   std::vector<base::string16> additional_param_names;
   std::vector<base::string16> additional_param_values;
-  if (!IsPepperCdmRegistered(kWidevineCdmPluginMimeType,
-                             &additional_param_names,
-                             &additional_param_values)) {
+  if (!IsPepperCdmAvailable(kWidevineCdmPluginMimeType,
+                            &additional_param_names,
+                            &additional_param_values)) {
     DVLOG(1) << "Widevine CDM is not currently available.";
     return;
   }
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index 22005ec..47bc09e 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -1703,13 +1703,10 @@
         // |is_modifiable| value until they are fully loaded, which occurs when
         // DidStopLoading() is called. Defer showing the preview until then.
       } else {
-        // TODO(japhet): This delay is a terrible hack. See crbug.com/376969
-        // for the motivation.
-        base::MessageLoop::current()->PostDelayedTask(
+        base::MessageLoop::current()->PostTask(
             FROM_HERE,
             base::Bind(&PrintWebViewHelper::ShowScriptedPrintPreview,
-                       weak_ptr_factory_.GetWeakPtr()),
-            base::TimeDelta::FromMilliseconds(100));
+                       weak_ptr_factory_.GetWeakPtr()));
       }
       IPC::SyncMessage* msg =
           new PrintHostMsg_SetupScriptedPrintPreview(routing_id());
diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
index 99ca8bc..c666d32 100644
--- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
@@ -241,6 +241,9 @@
     AppWindow.prototype.isAlwaysOnTop = function() {
       return appWindowData.alwaysOnTop;
     };
+    AppWindow.prototype.alphaEnabled = function() {
+      return appWindowData.alphaEnabled;
+    }
     AppWindow.prototype.handleWindowFirstShownForTests = function(callback) {
       // This allows test apps to get have their callback run even if they
       // call this after the first show has happened.
@@ -301,7 +304,8 @@
       alwaysOnTop: params.alwaysOnTop,
       hasFrameColor: params.hasFrameColor,
       activeFrameColor: params.activeFrameColor,
-      inactiveFrameColor: params.inactiveFrameColor
+      inactiveFrameColor: params.inactiveFrameColor,
+      alphaEnabled: params.alphaEnabled
     };
     currentAppWindow = new AppWindow;
   });
@@ -348,6 +352,9 @@
       (oldData.minimized && !update.minimized) ||
       (oldData.maximized && !update.maximized))
     dispatchEventIfExists(currentWindow, "onRestored");
+
+  if (oldData.alphaEnabled !== update.alphaEnabled)
+    dispatchEventIfExists(currentWindow, "onAlphaEnabledChanged");
 };
 
 function onAppWindowShownForTests() {
diff --git a/chrome/test/base/chrome_unit_test_suite.cc b/chrome/test/base/chrome_unit_test_suite.cc
index 9e40a65..ca239cd 100644
--- a/chrome/test/base/chrome_unit_test_suite.cc
+++ b/chrome/test/base/chrome_unit_test_suite.cc
@@ -6,7 +6,6 @@
 
 #include "base/path_service.h"
 #include "base/process/process_handle.h"
-#include "base/metrics/stats_table.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/common/chrome_content_client.h"
@@ -98,12 +97,6 @@
   InitializeProviders();
   RegisterInProcessThreads();
 
-  // Create an anonymous stats table since we don't need to share between
-  // processes.
-  stats_table_.reset(
-      new base::StatsTable(base::StatsTable::TableIdentifier(), 20, 200));
-  base::StatsTable::set_current(stats_table_.get());
-
   ChromeTestSuite::Initialize();
 
   // This needs to run after ChromeTestSuite::Initialize which calls content's
@@ -113,10 +106,6 @@
 
 void ChromeUnitTestSuite::Shutdown() {
   ResourceBundle::CleanupSharedInstance();
-
-  base::StatsTable::set_current(NULL);
-  stats_table_.reset();
-
   ChromeTestSuite::Shutdown();
 }
 
diff --git a/chrome/test/base/chrome_unit_test_suite.h b/chrome/test/base/chrome_unit_test_suite.h
index 0ac9eb4..1c1ddbd 100644
--- a/chrome/test/base/chrome_unit_test_suite.h
+++ b/chrome/test/base/chrome_unit_test_suite.h
@@ -10,10 +10,6 @@
 #include "base/files/file_path.h"
 #include "chrome/test/base/chrome_test_suite.h"
 
-namespace base {
-class StatsTable;
-}
-
 // Test suite for unit tests. Creates additional stub services that are not
 // needed for browser tests (e.g. a TestingBrowserProcess).
 class ChromeUnitTestSuite : public ChromeTestSuite {
@@ -32,7 +28,6 @@
   static void InitializeResourceBundle();
 
  private:
-  scoped_ptr<base::StatsTable> stats_table_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeUnitTestSuite);
 };
diff --git a/components/breakpad/app/breakpad_win.cc b/components/breakpad/app/breakpad_win.cc
index 1f6a3c4..56c4cf9 100644
--- a/components/breakpad/app/breakpad_win.cc
+++ b/components/breakpad/app/breakpad_win.cc
@@ -573,6 +573,10 @@
       google_breakpad::ExceptionHandler::HANDLER_NONE,
       dump_type, pipe_name.c_str(), custom_info);
 
+  // Set the DumpWithoutCrashingFunction for this instance of base.lib.  Other
+  // executable images linked with base should set this again for
+  // DumpWithoutCrashing to function correctly.
+  // See chrome_main.cc for example.
   base::debug::SetDumpWithoutCrashingFunction(&DumpProcessWithoutCrash);
 
   if (g_breakpad->IsOutOfProcess()) {
diff --git a/components/policy/core/common/cloud/enterprise_metrics.cc b/components/policy/core/common/cloud/enterprise_metrics.cc
index 12394fa..b541e80 100644
--- a/components/policy/core/common/cloud/enterprise_metrics.cc
+++ b/components/policy/core/common/cloud/enterprise_metrics.cc
@@ -9,6 +9,7 @@
 const char kMetricToken[] = "Enterprise.DMToken";
 const char kMetricPolicy[] = "Enterprise.Policy";
 const char kMetricEnrollment[] = "Enterprise.Enrollment";
+const char kMetricEnrollmentRecovery[] = "Enterprise.EnrollmentRecovery";
 const char kMetricPolicyRefresh[] = "Enterprise.PolicyRefresh";
 const char kMetricPolicyInvalidations[] = "Enterprise.PolicyInvalidations";
 
diff --git a/components/policy/core/common/cloud/enterprise_metrics.h b/components/policy/core/common/cloud/enterprise_metrics.h
index daac653..79bdcf1 100644
--- a/components/policy/core/common/cloud/enterprise_metrics.h
+++ b/components/policy/core/common/cloud/enterprise_metrics.h
@@ -167,6 +167,10 @@
   kMetricEnrollmentDeprovisioned,
   // Enrollment failed because the device doesn't belong to the domain.
   kMetricEnrollmentDomainMismatch,
+  // Enrollment has been triggered, the credential screen has been shown.
+  kMetricEnrollmentTriggered,
+  // The user retried to submitted credentials.
+  kMetricEnrollmentRetried,
 
   kMetricEnrollmentSize  // Must be the last.
 };
@@ -212,6 +216,7 @@
 POLICY_EXPORT extern const char kMetricToken[];
 POLICY_EXPORT extern const char kMetricPolicy[];
 POLICY_EXPORT extern const char kMetricEnrollment[];
+POLICY_EXPORT extern const char kMetricEnrollmentRecovery[];
 POLICY_EXPORT extern const char kMetricPolicyRefresh[];
 POLICY_EXPORT extern const char kMetricPolicyInvalidations[];
 
diff --git a/content/browser/frame_host/debug_urls.cc b/content/browser/frame_host/debug_urls.cc
index 733f899..ae454ae 100644
--- a/content/browser/frame_host/debug_urls.cc
+++ b/content/browser/frame_host/debug_urls.cc
@@ -174,6 +174,7 @@
     return true;
 
   return url == GURL(kChromeUICrashURL) ||
+         url == GURL(kChromeUIDumpURL) ||
          url == GURL(kChromeUIKillURL) ||
          url == GURL(kChromeUIHangURL) ||
          url == GURL(kChromeUIShorthangURL);
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc
index 87d9969..cfcfd5a 100644
--- a/content/browser/media/media_canplaytype_browsertest.cc
+++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -358,9 +358,13 @@
   EXPECT_EQ(kNot, CanPlay("'video/mpeg'"));
   EXPECT_EQ(kNot, CanPlay("'video/x-mp3'"));
 
-  // audio/mpeg does not allow any codecs parameter
+  // audio/mpeg without a codecs parameter (RFC 3003 compliant)
   EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg'"));
 
+  // audio/mpeg with mp3 in codecs parameter. (Not RFC compliant, but
+  // very common in the wild so it is a defacto standard).
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp3\"'"));
+
   EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1\"'"));
   EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3\"'"));
 
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.h b/content/browser/renderer_host/compositing_iosurface_layer_mac.h
index 9103314..0449ae7 100644
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.h
@@ -64,6 +64,8 @@
 // Called when a new frame is received.
 - (void)gotNewFrame;
 
+- (void)setNeedsDisplayAndDisplayAndAck;
+- (void)displayIfNeededAndAck;
 @end
 
 #endif  // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
index 040d8f9..bda4c5f 100644
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
@@ -18,7 +18,6 @@
 #include "ui/gl/gpu_switching_manager.h"
 
 @interface CompositingIOSurfaceLayer(Private)
-- (void)immediatelyForceDisplayAndAck;
 - (void)ackPendingFrame:(bool)success;
 - (void)timerFired;
 @end
@@ -101,7 +100,7 @@
   if (context_ && context_->is_vsync_disabled()) {
     // If vsync is disabled, draw immediately and don't bother trying to use
     // the isAsynchronous property to ensure smooth animation.
-    [self immediatelyForceDisplayAndAck];
+    [self setNeedsDisplayAndDisplayAndAck];
   } else {
     needs_display_ = YES;
     if (![self isAsynchronous])
@@ -111,8 +110,20 @@
 
 // Private methods:
 
-- (void)immediatelyForceDisplayAndAck {
+- (void)setNeedsDisplayAndDisplayAndAck {
+  // Workaround for crbug.com/395827
+  if ([self isAsynchronous])
+    [self setAsynchronous:NO];
+
   [self setNeedsDisplay];
+  [self displayIfNeededAndAck];
+}
+
+- (void)displayIfNeededAndAck {
+  // Workaround for crbug.com/395827
+  if ([self isAsynchronous])
+    [self setAsynchronous:NO];
+
   [self displayIfNeeded];
 
   // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
@@ -134,7 +145,7 @@
 
 - (void)timerFired {
   if (has_pending_frame_)
-    [self immediatelyForceDisplayAndAck];
+    [self setNeedsDisplayAndDisplayAndAck];
 }
 
 // The remaining methods implement the CAOpenGLLayer interface.
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 6232bcd..47f037d 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -341,9 +341,14 @@
 }
 
 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
-  root_layer_->RemoveAllChildren();
-  if (root_layer)
+  if (subroot_layer_) {
+    subroot_layer_->RemoveFromParent();
+    subroot_layer_ = NULL;
+  }
+  if (root_layer) {
+    subroot_layer_ = root_layer;
     root_layer_->AddChild(root_layer);
+  }
 }
 
 void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index e3cc42e..4792d90 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -132,7 +132,11 @@
       bool is_transient);
   void OnGpuChannelEstablished();
 
+  // root_layer_ is the persistent internal root layer, while subroot_layer_
+  // is the one attached by the compositor client.
   scoped_refptr<cc::Layer> root_layer_;
+  scoped_refptr<cc::Layer> subroot_layer_;
+
   scoped_ptr<cc::LayerTreeHost> host_;
   content::UIResourceProviderImpl ui_resource_provider_;
 
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h
index bb3bd03..1b30815 100644
--- a/content/browser/renderer_host/input/input_router.h
+++ b/content/browser/renderer_host/input/input_router.h
@@ -63,6 +63,8 @@
     MOBILE_VIEWPORT   = 1 << 1
   };
   virtual void OnViewUpdated(int view_flags) = 0;
+
+  virtual bool HasPendingEvents() const = 0;
 };
 
 }  // namespace content
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h
index b49c778..e06113b 100644
--- a/content/browser/renderer_host/input/input_router_impl.h
+++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -74,6 +74,7 @@
   virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE;
   virtual bool ShouldForwardTouchEvent() const OVERRIDE;
   virtual void OnViewUpdated(int view_flags) OVERRIDE;
+  virtual bool HasPendingEvents() const OVERRIDE;
 
   // IPC::Listener
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -205,8 +206,6 @@
   // all events have been dispatched (i.e., |HasPendingEvents()| is false).
   void SignalFlushedIfNecessary();
 
-  bool HasPendingEvents() const;
-
   bool IsInOverscrollGesture() const;
 
   int routing_id() const { return routing_id_; }
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 2be9ec7..86799c9 100644
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -25,9 +25,6 @@
 // accessibility support.
 const int kIdScreenReaderHoneyPot = 1;
 
-// A version of the OBJID_CLIENT constant that works in 64-bit mode too.
-static const LPARAM kObjIdClient = static_cast<ULONG>(OBJID_CLIENT);
-
 LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
   ::DestroyWindow(hwnd());
 }
@@ -138,14 +135,18 @@
 LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
                                                 WPARAM w_param,
                                                 LPARAM l_param) {
-  if (kIdScreenReaderHoneyPot == l_param) {
+  // Only the lower 32 bits of l_param are valid when checking the object id
+  // because it sometimes gets sign-extended incorrectly (but not always).
+  DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param));
+
+  if (kIdScreenReaderHoneyPot == obj_id) {
     // When an MSAA client has responded to our fake event on this id,
     // enable screen reader support.
     BrowserAccessibilityState::GetInstance()->OnScreenReaderDetected();
     return static_cast<LRESULT>(0L);
   }
 
-  if (kObjIdClient != l_param || !manager_)
+  if (OBJID_CLIENT != obj_id || !manager_)
     return static_cast<LRESULT>(0L);
 
   base::win::ScopedComPtr<IAccessible> root(
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 52a3890..a0037f3 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1189,10 +1189,6 @@
 
   waiting_for_screen_rects_ack_ = false;
 
-  // Reset to ensure that input routing works with a new renderer.
-  input_router_.reset(new InputRouterImpl(
-      process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
-
   // Must reset these to ensure that keyboard events work with a new renderer.
   suppress_next_char_events_ = false;
 
@@ -1211,6 +1207,13 @@
     view_ = NULL;  // The View should be deleted by RenderProcessGone.
   }
 
+  // Reconstruct the input router to ensure that it has fresh state for a new
+  // renderer. Otherwise it may be stuck waiting for the old renderer to ack an
+  // event. (In particular, the above call to view_->RenderProcessGone will
+  // destroy the aura window, which may dispatch a synthetic mouse move.)
+  input_router_.reset(new InputRouterImpl(
+      process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
+
   synthetic_gesture_controller_.reset();
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 0e6a9d1..710719c 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -104,6 +104,7 @@
   }
   virtual bool ShouldForwardTouchEvent() const OVERRIDE { return true; }
   virtual void OnViewUpdated(int view_flags) OVERRIDE {}
+  virtual bool HasPendingEvents() const OVERRIDE { return false; }
 
   // IPC::Listener
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
@@ -327,6 +328,17 @@
       return mock_physical_backing_size_;
     return TestRenderWidgetHostView::GetPhysicalBackingSize();
   }
+#if defined(USE_AURA)
+  virtual ~TestView() {
+    // Simulate the mouse exit event dispatched when an aura window is
+    // destroyed. (MakeWebMouseEventFromAuraEvent translates ET_MOUSE_EXITED
+    // into WebInputEvent::MouseMove.)
+    rwh_->input_router()->SendMouseEvent(
+        MouseEventWithLatencyInfo(
+            SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove),
+            ui::LatencyInfo()));
+  }
+#endif
 
  protected:
   WebMouseWheelEvent unhandled_wheel_event_;
@@ -1416,4 +1428,13 @@
   SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED);
 }
 
+TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
+  // RendererExited will delete the view.
+  host_->SetView(new TestView(host_.get()));
+  host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+
+  // Make sure the input router is in a fresh state.
+  ASSERT_FALSE(host_->input_router()->HasPendingEvents());
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index dce9a5e..553ded7 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -800,6 +800,9 @@
 
   // Call setNeedsDisplay before pausing for new frames to come in -- if any
   // do, and are drawn, then the needsDisplay bit will be cleared.
+  // Workaround for crbug.com/395827
+  if ([compositing_iosurface_layer_ isAsynchronous])
+    [compositing_iosurface_layer_ setAsynchronous:NO];
   [compositing_iosurface_layer_ setNeedsDisplay];
   PauseForPendingResizeOrRepaintsAndDraw();
 }
@@ -1698,8 +1701,8 @@
 }
 
 void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() {
-  if (compositing_iosurface_)
-    compositing_iosurface_->UnrefIOSurface();
+  if (!render_widget_host_->is_hidden())
+    DestroyCompositedIOSurfaceAndLayer();
 }
 
 void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() {
@@ -2173,7 +2176,7 @@
   // to keep the window and the window's contents in sync.
   [cocoa_view_ displayIfNeeded];
   [software_layer_ displayIfNeeded];
-  [compositing_iosurface_layer_ displayIfNeeded];
+  [compositing_iosurface_layer_ displayIfNeededAndAck];
 }
 
 void RenderWidgetHostViewMac::LayoutLayers() {
@@ -2224,8 +2227,10 @@
       // displayed. Calling displayIfNeeded will ensure that the right size
       // frame is drawn to the screen.
       // http://crbug.com/350817
-      [compositing_iosurface_layer_ setNeedsDisplay];
-      [compositing_iosurface_layer_ displayIfNeeded];
+      // Workaround for crbug.com/395827
+      if ([compositing_iosurface_layer_ isAsynchronous])
+        [compositing_iosurface_layer_ setAsynchronous:NO];
+      [compositing_iosurface_layer_ setNeedsDisplayAndDisplayAndAck];
     }
   }
 
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
index 11fe636..c65a2d6 100644
--- a/content/content_browser.target.darwin-arm.mk
+++ b/content/content_browser.target.darwin-arm.mk
@@ -680,6 +680,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -870,6 +871,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-arm64.mk b/content/content_browser.target.darwin-arm64.mk
index 429d5ae..3a28f73 100644
--- a/content/content_browser.target.darwin-arm64.mk
+++ b/content/content_browser.target.darwin-arm64.mk
@@ -669,6 +669,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -847,6 +848,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-mips.mk b/content/content_browser.target.darwin-mips.mk
index dafd7a6..d1b3523 100644
--- a/content/content_browser.target.darwin-mips.mk
+++ b/content/content_browser.target.darwin-mips.mk
@@ -674,6 +674,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -858,6 +859,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
index 8a84133..9358c7e 100644
--- a/content/content_browser.target.darwin-x86.mk
+++ b/content/content_browser.target.darwin-x86.mk
@@ -674,6 +674,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.darwin-x86_64.mk b/content/content_browser.target.darwin-x86_64.mk
index 92cc0a8..c84ecec 100644
--- a/content/content_browser.target.darwin-x86_64.mk
+++ b/content/content_browser.target.darwin-x86_64.mk
@@ -674,6 +674,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index 11fe636..c65a2d6 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -680,6 +680,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -870,6 +871,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-arm64.mk b/content/content_browser.target.linux-arm64.mk
index 429d5ae..3a28f73 100644
--- a/content/content_browser.target.linux-arm64.mk
+++ b/content/content_browser.target.linux-arm64.mk
@@ -669,6 +669,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -847,6 +848,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-mips.mk b/content/content_browser.target.linux-mips.mk
index dafd7a6..d1b3523 100644
--- a/content/content_browser.target.linux-mips.mk
+++ b/content/content_browser.target.linux-mips.mk
@@ -674,6 +674,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -858,6 +859,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index 8a84133..9358c7e 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -674,6 +674,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/content_browser.target.linux-x86_64.mk b/content/content_browser.target.linux-x86_64.mk
index 92cc0a8..c84ecec 100644
--- a/content/content_browser.target.linux-x86_64.mk
+++ b/content/content_browser.target.linux-x86_64.mk
@@ -674,6 +674,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
@@ -857,6 +858,7 @@
 	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
 	$(LOCAL_PATH)/third_party/leveldatabase/src \
 	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(gyp_shared_intermediate_dir)/angle \
 	$(LOCAL_PATH)/third_party/WebKit \
 	$(LOCAL_PATH)/third_party/npapi \
 	$(LOCAL_PATH)/third_party/npapi/bindings \
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index a19b8b1..ac65ded 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -33,6 +33,7 @@
 const char kChromeUIWebRTCInternalsHost[] = "webrtc-internals";
 
 const char kChromeUICrashURL[] = "chrome://crash";
+const char kChromeUIDumpURL[] = "chrome://crashdump";
 const char kChromeUIGpuCleanURL[] = "chrome://gpuclean";
 const char kChromeUIGpuCrashURL[] = "chrome://gpucrash";
 const char kChromeUIGpuHangURL[] = "chrome://gpuhang";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index d1d0ddc..7f125f7 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -42,6 +42,7 @@
 
 // Full about URLs (including schemes).
 CONTENT_EXPORT extern const char kChromeUICrashURL[];
+CONTENT_EXPORT extern const char kChromeUIDumpURL[];
 CONTENT_EXPORT extern const char kChromeUIGpuCleanURL[];
 CONTENT_EXPORT extern const char kChromeUIGpuCrashURL[];
 CONTENT_EXPORT extern const char kChromeUIGpuHangURL[];
diff --git a/content/renderer/media/crypto/key_systems.cc b/content/renderer/media/crypto/key_systems.cc
index 6cd8218..dace751 100644
--- a/content/renderer/media/crypto/key_systems.cc
+++ b/content/renderer/media/crypto/key_systems.cc
@@ -10,6 +10,8 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/eme_codec.h"
 #include "content/public/renderer/content_renderer_client.h"
@@ -87,6 +89,8 @@
  public:
   static KeySystems& GetInstance();
 
+  void UpdateIfNeeded();
+
   bool IsConcreteSupportedKeySystem(const std::string& key_system);
 
   bool IsSupportedKeySystemWithMediaMimeType(
@@ -104,6 +108,8 @@
   void AddCodecMask(const std::string& codec, uint32 mask);
 
  private:
+  void UpdateSupportedKeySystems();
+
   void AddConcreteSupportedKeySystems(
       const std::vector<KeySystemInfo>& concrete_key_systems);
 
@@ -161,18 +167,26 @@
   CodecMaskMap container_codec_masks_;
   CodecMaskMap codec_masks_;
 
+  bool needs_update_;
+  base::Time last_update_time_;
+
+  // Makes sure all methods are called from the same thread.
+  base::ThreadChecker thread_checker_;
+
   DISALLOW_COPY_AND_ASSIGN(KeySystems);
 };
 
 static base::LazyInstance<KeySystems> g_key_systems = LAZY_INSTANCE_INITIALIZER;
 
 KeySystems& KeySystems::GetInstance() {
-  return g_key_systems.Get();
+  KeySystems& key_systems = g_key_systems.Get();
+  key_systems.UpdateIfNeeded();
+  return key_systems;
 }
 
 // Because we use a LazyInstance, the key systems info must be populated when
 // the instance is lazily initiated.
-KeySystems::KeySystems() {
+KeySystems::KeySystems() : needs_update_(true) {
   // Build container and codec masks for quick look up.
   for (size_t i = 0; i < arraysize(kContainerCodecMasks); ++i) {
     const CodecMask& container_codec_mask = kContainerCodecMasks[i];
@@ -187,18 +201,60 @@
     codec_masks_[codec_mask.type] = codec_mask.mask;
   }
 
-  std::vector<KeySystemInfo> key_systems_info;
-  GetContentClient()->renderer()->AddKeySystems(&key_systems_info);
-  // Clear Key is always supported.
-  AddClearKey(&key_systems_info);
-  AddConcreteSupportedKeySystems(key_systems_info);
+  UpdateSupportedKeySystems();
+
 #if defined(WIDEVINE_CDM_AVAILABLE)
   key_systems_support_uma_.AddKeySystemToReport(kWidevineKeySystem);
 #endif  // defined(WIDEVINE_CDM_AVAILABLE)
 }
 
+void KeySystems::UpdateIfNeeded() {
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!needs_update_)
+    return;
+
+  // The update could involve a sync IPC to the browser process. Use a minimum
+  // update interval to avoid unnecessary frequent IPC to the browser.
+  static const int kMinUpdateIntervalInSeconds = 5;
+  base::Time now = base::Time::Now();
+  if (now - last_update_time_ <
+      base::TimeDelta::FromSeconds(kMinUpdateIntervalInSeconds)) {
+    return;
+  }
+
+  UpdateSupportedKeySystems();
+#endif
+}
+
+void KeySystems::UpdateSupportedKeySystems() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(needs_update_);
+  concrete_key_system_map_.clear();
+  parent_key_system_map_.clear();
+
+  // Build KeySystemInfo.
+  std::vector<KeySystemInfo> key_systems_info;
+  GetContentClient()->renderer()->AddKeySystems(&key_systems_info);
+  // Clear Key is always supported.
+  AddClearKey(&key_systems_info);
+
+  AddConcreteSupportedKeySystems(key_systems_info);
+
+#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
+  if (IsConcreteSupportedKeySystem(kWidevineKeySystem))
+    needs_update_ = false;
+#endif
+
+  last_update_time_ = base::Time::Now();
+}
+
 void KeySystems::AddConcreteSupportedKeySystems(
     const std::vector<KeySystemInfo>& concrete_key_systems) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(concrete_key_system_map_.empty());
+  DCHECK(parent_key_system_map_.empty());
+
   for (size_t i = 0; i < concrete_key_systems.size(); ++i) {
     const KeySystemInfo& key_system_info = concrete_key_systems[i];
     AddConcreteSupportedKeySystem(key_system_info.key_system,
@@ -219,6 +275,7 @@
 #endif
     SupportedCodecs supported_codecs,
     const std::string& parent_key_system) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system))
       << "Key system '" << concrete_key_system << "' already registered";
   DCHECK(parent_key_system_map_.find(concrete_key_system) ==
@@ -247,6 +304,7 @@
 }
 
 bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   return concrete_key_system_map_.find(key_system) !=
       concrete_key_system_map_.end();
 }
@@ -254,6 +312,7 @@
 bool KeySystems::IsSupportedContainer(
     const std::string& container,
     SupportedCodecs key_system_supported_codecs) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!container.empty());
 
   // When checking container support for EME, "audio/foo" should be treated the
@@ -280,6 +339,7 @@
     const std::string& container,
     const std::vector<std::string>& codecs,
     SupportedCodecs key_system_supported_codecs) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!container.empty());
   DCHECK(!codecs.empty());
   DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
@@ -312,6 +372,8 @@
     const std::string& mime_type,
     const std::vector<std::string>& codecs,
     const std::string& key_system) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
   // If |key_system| is a parent key_system, use its concrete child.
   // Otherwise, use |key_system|.
   std::string concrete_key_system;
@@ -356,6 +418,8 @@
 }
 
 bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
   KeySystemPropertiesMap::iterator key_system_iter =
       concrete_key_system_map_.find(concrete_key_system);
   if (key_system_iter == concrete_key_system_map_.end()) {
@@ -368,6 +432,8 @@
 
 #if defined(ENABLE_PEPPER_CDMS)
 std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
   KeySystemPropertiesMap::iterator key_system_iter =
       concrete_key_system_map_.find(concrete_key_system);
   if (key_system_iter == concrete_key_system_map_.end()) {
@@ -382,13 +448,17 @@
 #endif
 
 void KeySystems::AddContainerMask(const std::string& container, uint32 mask) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(container_codec_masks_.find(container) ==
          container_codec_masks_.end());
+
   container_codec_masks_[container] = static_cast<EmeCodec>(mask);
 }
 
 void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) {
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(codec_masks_.find(codec) == codec_masks_.end());
+
   codec_masks_[codec] = static_cast<EmeCodec>(mask);
 }
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index fc74021..65c8b7a 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -287,6 +287,12 @@
     return;
   if (url == GURL(kChromeUICrashURL)) {
     CrashIntentionally();
+  } else if (url == GURL(kChromeUIDumpURL)) {
+    // This URL will only correctly create a crash dump file if content is
+    // hosted in a process that has correctly called
+    // base::debug::SetDumpWithoutCrashingFunction.  Refer to the documentation
+    // of base::debug::DumpWithoutCrashing for more details.
+    base::debug::DumpWithoutCrashing();
   } else if (url == GURL(kChromeUIKillURL)) {
     base::KillProcess(base::GetCurrentProcessHandle(), 1, false);
   } else if (url == GURL(kChromeUIHangURL)) {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index c0b60f6..381b96c 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -307,7 +307,7 @@
   if (host != common_host_) {
     common_host_ = host;
     common_host_histogram_suffix_ = HostToCustomHistogramSuffix(host);
-    v8::V8::SetCreateHistogramFunction(CreateHistogram);
+    blink::mainThreadIsolate()->SetCreateHistogramFunction(CreateHistogram);
   }
 }
 
@@ -333,10 +333,6 @@
       base::PlatformThread::CurrentId(),
       kTraceEventRendererMainThreadSortIndex);
 
-  v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
-  v8::V8::SetCreateHistogramFunction(CreateHistogram);
-  v8::V8::SetAddHistogramSampleFunction(AddHistogramSample);
-
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
   // On Mac and Android, the select popups are rendered by the browser.
   blink::WebView::setUseExternalPopupMenus(true);
@@ -737,6 +733,12 @@
   webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
   blink::initialize(webkit_platform_support_.get());
 
+  v8::Isolate* isolate = blink::mainThreadIsolate();
+
+  isolate->SetCounterFunction(base::StatsTable::FindLocation);
+  isolate->SetCreateHistogramFunction(CreateHistogram);
+  isolate->SetAddHistogramSampleFunction(AddHistogramSample);
+
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
 
   bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing);
diff --git a/content/test/test_webkit_platform_support.cc b/content/test/test_webkit_platform_support.cc
index 0e9aaf0..a55ebf6 100644
--- a/content/test/test_webkit_platform_support.cc
+++ b/content/test/test_webkit_platform_support.cc
@@ -42,9 +42,16 @@
 TestWebKitPlatformSupport::TestWebKitPlatformSupport() {
   url_loader_factory_.reset(new WebURLLoaderMockFactory());
   mock_clipboard_.reset(new MockWebClipboardImpl());
-  v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
+
+  // Create an anonymous stats table since we don't need to share between
+  // processes.
+  stats_table_.reset(
+      new base::StatsTable(base::StatsTable::TableIdentifier(), 20, 200));
+  base::StatsTable::set_current(stats_table_.get());
 
   blink::initialize(this);
+  blink::mainThreadIsolate()->SetCounterFunction(
+      base::StatsTable::FindLocation);
   blink::setLayoutTestMode(true);
   blink::WebSecurityPolicy::registerURLSchemeAsLocal(
       blink::WebString::fromUTF8("test-shell-resource"));
@@ -97,6 +104,8 @@
   url_loader_factory_.reset();
   mock_clipboard_.reset();
   blink::shutdown();
+  base::StatsTable::set_current(NULL);
+  stats_table_.reset();
 }
 
 blink::WebMimeRegistry* TestWebKitPlatformSupport::mimeRegistry() {
diff --git a/content/test/test_webkit_platform_support.h b/content/test/test_webkit_platform_support.h
index 469d6bf..3c983dc 100644
--- a/content/test/test_webkit_platform_support.h
+++ b/content/test/test_webkit_platform_support.h
@@ -15,6 +15,10 @@
 #include "content/test/weburl_loader_mock_factory.h"
 #include "third_party/WebKit/public/platform/WebUnitTestSupport.h"
 
+namespace base {
+class StatsTable;
+}
+
 namespace blink {
 class WebLayerTreeView;
 }
@@ -91,6 +95,7 @@
   base::ScopedTempDir file_system_root_;
   scoped_ptr<WebURLLoaderMockFactory> url_loader_factory_;
   WebCompositorSupportImpl compositor_support_;
+  scoped_ptr<base::StatsTable> stats_table_;
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
   blink::WebThemeEngine* active_theme_engine_;
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 79cb6c0..b1e59a8 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -658,8 +658,15 @@
 void InProcessCommandBuffer::RetireSyncPointOnGpuThread(uint32 sync_point) {
   gles2::MailboxManager* mailbox_manager =
       decoder_->GetContextGroup()->mailbox_manager();
-  if (mailbox_manager->UsesSync() && MakeCurrent())
-    mailbox_manager->PushTextureUpdates();
+  if (mailbox_manager->UsesSync()) {
+    bool make_current_success = false;
+    {
+      base::AutoLock lock(command_buffer_lock_);
+      make_current_success = MakeCurrent();
+    }
+    if (make_current_success)
+      mailbox_manager->PushTextureUpdates();
+  }
   g_sync_point_manager.Get().RetireSyncPoint(sync_point);
 }
 
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index c668fbf..bcd2dd4 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": "6.5",
+  "version": "6.7",
   "entries": [
     {
       "id": 1,
@@ -1082,6 +1082,18 @@
       "features": [
         "disable_async_readpixels"
       ]
+    },
+    {
+      "id": 86,
+      "description": "Disable use of Direct3D 11 on Matrox video cards",
+      "cr_bugs": [395861],
+      "os": {
+        "type": "win"
+      },
+      "vendor_id": "0x102b",
+      "features": [
+        "disable_d3d11"
+      ]
     }
   ]
 }
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index 2f02da1..9b02c4c 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -460,7 +460,12 @@
   { "video/ogg", "opus,theora,vorbis" },
   { "audio/ogg", "opus,vorbis" },
   { "application/ogg", "opus,theora,vorbis" },
-  { "audio/mpeg", "" },
+  { "audio/mpeg", ",mp3" }, // Note: The comma before the 'mp3'results in an
+                            // empty string codec ID and indicates
+                            // a missing codecs= parameter is also valid.
+                            // The presense of 'mp3' is not RFC compliant,
+                            // but is common in the wild so it is a defacto
+                            // standard.
   { "audio/mp3", "" },
   { "audio/x-mp3", "" }
 };
@@ -475,11 +480,19 @@
   if (supported_codecs.empty())
     return codecs.empty();
 
+  // If no codecs are specified in the mimetype, check to see if a missing
+  // codecs parameter is allowed.
+  if (codecs.empty())
+    return supported_codecs.find(std::string()) != supported_codecs.end();
+
   for (size_t i = 0; i < codecs.size(); ++i) {
-    if (supported_codecs.find(codecs[i]) == supported_codecs.end())
+    if (codecs[i].empty() ||
+        supported_codecs.find(codecs[i]) == supported_codecs.end()) {
       return false;
+    }
   }
-  return !codecs.empty();
+
+  return true;
 }
 
 void MimeUtil::InitializeMimeTypeMaps() {
diff --git a/pdf/instance.cc b/pdf/instance.cc
index a17db57..5c71bbf 100644
--- a/pdf/instance.cc
+++ b/pdf/instance.cc
@@ -349,6 +349,10 @@
     // For PDFs embedded in a frame, we don't get the data automatically like we
     // do for full-frame loads.  Start loading the data manually.
     LoadUrl(url);
+  } else {
+    DCHECK(!did_call_start_loading_);
+    pp::PDF::DidStartLoading(this);
+    did_call_start_loading_ = true;
   }
 
   ZoomLimitsChanged(kMinZoom, kMaxZoom);
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi
index 47d60fa..3571924 100644
--- a/remoting/remoting_host.gypi
+++ b/remoting/remoting_host.gypi
@@ -795,6 +795,7 @@
               },
               'mac_bundle_resources': [
                 '<(PRODUCT_DIR)/icudtl.dat',
+                'host/disconnect_window.xib',
                 'host/it2me/remote_assistance_host-Info.plist',
                 '<!@pymod_do_main(remoting_copy_locales -o -p <(OS) -x <(PRODUCT_DIR) <(remoting_locales))',
 
diff --git a/sandbox/win/src/handle_closer_agent.cc b/sandbox/win/src/handle_closer_agent.cc
index be0ffc1..07c6a09 100644
--- a/sandbox/win/src/handle_closer_agent.cc
+++ b/sandbox/win/src/handle_closer_agent.cc
@@ -78,7 +78,7 @@
 bool HandleCloserAgent::CloseHandles() {
   DWORD handle_count = UINT_MAX;
   const int kInvalidHandleThreshold = 100;
-  const size_t kHandleOffset = sizeof(HANDLE);
+  const size_t kHandleOffset = 4;  // Handles are always a multiple of 4.
 
   if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
     return false;
diff --git a/sandbox/win/src/handle_closer_test.cc b/sandbox/win/src/handle_closer_test.cc
index 9adcf6c..7fa2598 100644
--- a/sandbox/win/src/handle_closer_test.cc
+++ b/sandbox/win/src/handle_closer_test.cc
@@ -73,7 +73,7 @@
       // Brute force the handle table to find what we're looking for.
       DWORD handle_count = UINT_MAX;
       const int kInvalidHandleThreshold = 100;
-      const size_t kHandleOffset = sizeof(HANDLE);
+      const size_t kHandleOffset = 4;  // Handles are always a multiple of 4.
       HANDLE handle = NULL;
       int invalid_count = 0;
       base::string16 handle_name;
diff --git a/sync/internal_api/sync_backup_manager.cc b/sync/internal_api/sync_backup_manager.cc
index 295f79a..3295568 100644
--- a/sync/internal_api/sync_backup_manager.cc
+++ b/sync/internal_api/sync_backup_manager.cc
@@ -4,6 +4,7 @@
 
 #include "sync/internal_api/sync_backup_manager.h"
 
+#include "sync/internal_api/public/read_node.h"
 #include "sync/internal_api/public/write_transaction.h"
 #include "sync/syncable/directory.h"
 #include "sync/syncable/mutable_entry.h"
@@ -37,26 +38,24 @@
       ReportUnrecoverableErrorFunction
           report_unrecoverable_error_function,
       CancelationSignal* cancelation_signal) {
-  SyncRollbackManagerBase::Init(database_location, event_handler,
-                                sync_server_and_path, sync_server_port,
-                                use_ssl, post_factory.Pass(),
-                                workers, extensions_activity, change_delegate,
-                                credentials, invalidator_client_id,
-                                restored_key_for_bootstrapping,
-                                restored_keystore_key_for_bootstrapping,
-                                internal_components_factory, encryptor,
-                                unrecoverable_error_handler.Pass(),
-                                report_unrecoverable_error_function,
-                                cancelation_signal);
+  if (SyncRollbackManagerBase::InitInternal(
+          database_location,
+          internal_components_factory,
+          unrecoverable_error_handler.Pass(),
+          report_unrecoverable_error_function)) {
+    GetUserShare()->directory->CollectMetaHandleCounts(
+        &status_.num_entries_by_type, &status_.num_to_delete_entries_by_type);
 
-  GetUserShare()->directory->CollectMetaHandleCounts(
-      &status_.num_entries_by_type,
-      &status_.num_to_delete_entries_by_type);
+    HideSyncPreference(PRIORITY_PREFERENCES);
+    HideSyncPreference(PREFERENCES);
+  }
 }
 
 void SyncBackupManager::SaveChanges() {
-  NormalizeEntries();
-  GetUserShare()->directory->SaveChanges();
+  if (initialized()) {
+    NormalizeEntries();
+    GetUserShare()->directory->SaveChanges();
+  }
 }
 
 SyncStatus SyncBackupManager::GetDetailedStatus() const {
@@ -104,7 +103,7 @@
     if (!entry.GetId().ServerKnows())
       entry.PutId(syncable::Id::CreateFromServerId(entry.GetId().value()));
     if (!entry.GetParentId().ServerKnows()) {
-      entry.PutParentId(syncable::Id::CreateFromServerId(
+      entry.PutParentIdPropertyOnly(syncable::Id::CreateFromServerId(
           entry.GetParentId().value()));
     }
     entry.PutBaseVersion(1);
@@ -113,6 +112,34 @@
   unsynced_.clear();
 }
 
+void SyncBackupManager::HideSyncPreference(ModelType type) {
+  WriteTransaction trans(FROM_HERE, GetUserShare());
+  ReadNode pref_root(&trans);
+  if (BaseNode::INIT_OK != pref_root.InitTypeRoot(type))
+    return;
+
+  std::vector<int64> pref_ids;
+  pref_root.GetChildIds(&pref_ids);
+  for (uint32 i = 0; i < pref_ids.size(); ++i) {
+    syncable::MutableEntry entry(trans.GetWrappedWriteTrans(),
+                                 syncable::GET_BY_HANDLE, pref_ids[i]);
+    if (entry.good()) {
+      // HACKY: Set IS_DEL to true to remove entry from parent-children
+      // index so that it's not returned when syncable service asks
+      // for sync data. Syncable service then creates entry for local
+      // model. Then the existing entry is undeleted and set to local value
+      // because it has the same unique client tag.
+      entry.PutIsDel(true);
+      entry.PutIsUnsynced(false);
+
+      // Don't persist on disk so that if backup is aborted before receiving
+      // local preference values, values in sync DB are saved.
+      GetUserShare()->directory->UnmarkDirtyEntry(
+          trans.GetWrappedWriteTrans(), &entry);
+    }
+  }
+}
+
 void SyncBackupManager::RegisterDirectoryTypeDebugInfoObserver(
     syncer::TypeDebugInfoObserver* observer) {}
 
diff --git a/sync/internal_api/sync_backup_manager.h b/sync/internal_api/sync_backup_manager.h
index e6b9ca4..aba58e2 100644
--- a/sync/internal_api/sync_backup_manager.h
+++ b/sync/internal_api/sync_backup_manager.h
@@ -61,6 +61,12 @@
   // entries.
   void NormalizeEntries();
 
+  // Manipulate preference nodes so that they'll be overwritten by local
+  // preference values during model association, i.e. local wins instead of
+  // server wins. This is for preventing backup from changing preferences in
+  // case backup DB has hijacked preferences.
+  void HideSyncPreference(ModelType pref_type);
+
   // Handles of unsynced entries caused by local model changes.
   std::set<int64> unsynced_;
 
diff --git a/sync/internal_api/sync_backup_manager_unittest.cc b/sync/internal_api/sync_backup_manager_unittest.cc
index 5472c02..c075354 100644
--- a/sync/internal_api/sync_backup_manager_unittest.cc
+++ b/sync/internal_api/sync_backup_manager_unittest.cc
@@ -5,15 +5,22 @@
 #include "sync/internal_api/sync_backup_manager.h"
 
 #include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
 #include "sync/internal_api/public/read_node.h"
 #include "sync/internal_api/public/read_transaction.h"
+#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
 #include "sync/internal_api/public/test/test_internal_components_factory.h"
 #include "sync/internal_api/public/write_node.h"
 #include "sync/internal_api/public/write_transaction.h"
 #include "sync/syncable/entry.h"
 #include "sync/test/test_directory_backing_store.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+
 namespace syncer {
 
 namespace {
@@ -22,16 +29,36 @@
   EXPECT_TRUE(success);
 }
 
-class SyncBackupManagerTest : public testing::Test {
+class SyncBackupManagerTest : public syncer::SyncManager::Observer,
+                              public testing::Test {
+ public:
+  MOCK_METHOD1(OnSyncCycleCompleted,
+               void(const sessions::SyncSessionSnapshot&));
+  MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));
+  MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));
+  MOCK_METHOD1(OnMigrationRequested, void(ModelTypeSet));;
+  MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));
+  MOCK_METHOD4(OnInitializationComplete,
+               void(const WeakHandle<JsBackend>&,
+                    const WeakHandle<DataTypeDebugInfoListener>&,
+                    bool, ModelTypeSet));
+
  protected:
   virtual void SetUp() OVERRIDE {
     CHECK(temp_dir_.CreateUniqueTempDir());
   }
 
-  void InitManager(SyncManager* manager) {
-    TestInternalComponentsFactory factory(InternalComponentsFactory::Switches(),
-                                          STORAGE_ON_DISK);
+  void InitManager(SyncManager* manager, StorageOption storage_option) {
+    manager_ = manager;
+    EXPECT_CALL(*this, OnInitializationComplete(_, _, _, _))
+        .WillOnce(WithArgs<2>(Invoke(this,
+                                     &SyncBackupManagerTest::HandleInit)));
 
+    TestInternalComponentsFactory factory(InternalComponentsFactory::Switches(),
+                                          storage_option);
+    manager->AddObserver(this);
+
+    base::RunLoop run_loop;
     manager->Init(temp_dir_.path(),
                   MakeWeakHandle(base::WeakPtr<JsEventHandler>()),
                   "", 0, true, scoped_ptr<HttpPostProviderFactory>().Pass(),
@@ -39,13 +66,8 @@
                   NULL, NULL, SyncCredentials(), "", "", "", &factory,
                   NULL, scoped_ptr<UnrecoverableErrorHandler>().Pass(),
                   NULL, NULL);
-    manager->ConfigureSyncer(
-          CONFIGURE_REASON_NEW_CLIENT,
-          ModelTypeSet(PREFERENCES),
-          ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
-          ModelSafeRoutingInfo(),
-          base::Bind(&OnConfigDone, true),
-          base::Bind(&OnConfigDone, false));
+    loop_.PostTask(FROM_HERE, run_loop.QuitClosure());
+    run_loop.Run();
   }
 
   void CreateEntry(UserShare* user_share, ModelType type,
@@ -59,22 +81,43 @@
               node.InitUniqueByCreation(type, type_root, client_tag));
   }
 
+ private:
+  void ConfigureSyncer() {
+    manager_->ConfigureSyncer(CONFIGURE_REASON_NEW_CLIENT,
+                              ModelTypeSet(SEARCH_ENGINES),
+                              ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
+                              ModelSafeRoutingInfo(),
+                              base::Bind(&OnConfigDone, true),
+                              base::Bind(&OnConfigDone, false));
+  }
+
+  void HandleInit(bool success) {
+    if (success) {
+      loop_.PostTask(FROM_HERE,
+                     base::Bind(&SyncBackupManagerTest::ConfigureSyncer,
+                                base::Unretained(this)));
+    } else {
+      manager_->ShutdownOnSyncThread();
+    }
+  }
+
   base::ScopedTempDir temp_dir_;
   base::MessageLoop loop_;    // Needed for WeakHandle
+  SyncManager* manager_;
 };
 
 TEST_F(SyncBackupManagerTest, NormalizeAndPersist) {
   scoped_ptr<SyncBackupManager> manager(new SyncBackupManager);
-  InitManager(manager.get());
+  InitManager(manager.get(), STORAGE_ON_DISK);
 
-  CreateEntry(manager->GetUserShare(), PREFERENCES, "test");
+  CreateEntry(manager->GetUserShare(), SEARCH_ENGINES, "test");
 
   {
     // New entry is local and unsynced at first.
     ReadTransaction trans(FROM_HERE, manager->GetUserShare());
     ReadNode pref(&trans);
     EXPECT_EQ(BaseNode::INIT_OK,
-              pref.InitByClientTagLookup(PREFERENCES, "test"));
+              pref.InitByClientTagLookup(SEARCH_ENGINES, "test"));
     EXPECT_FALSE(pref.GetEntry()->GetId().ServerKnows());
     EXPECT_TRUE(pref.GetEntry()->GetIsUnsynced());
   }
@@ -86,7 +129,7 @@
     ReadTransaction trans(FROM_HERE, manager->GetUserShare());
     ReadNode pref(&trans);
     EXPECT_EQ(BaseNode::INIT_OK,
-              pref.InitByClientTagLookup(PREFERENCES, "test"));
+              pref.InitByClientTagLookup(SEARCH_ENGINES, "test"));
     EXPECT_TRUE(pref.GetEntry()->GetId().ServerKnows());
     EXPECT_FALSE(pref.GetEntry()->GetIsUnsynced());
   }
@@ -94,17 +137,23 @@
 
   // Reopen db to verify entry is persisted.
   manager.reset(new SyncBackupManager);
-  InitManager(manager.get());
+  InitManager(manager.get(), STORAGE_ON_DISK);
   {
     ReadTransaction trans(FROM_HERE, manager->GetUserShare());
     ReadNode pref(&trans);
     EXPECT_EQ(BaseNode::INIT_OK,
-              pref.InitByClientTagLookup(PREFERENCES, "test"));
+              pref.InitByClientTagLookup(SEARCH_ENGINES, "test"));
     EXPECT_TRUE(pref.GetEntry()->GetId().ServerKnows());
     EXPECT_FALSE(pref.GetEntry()->GetIsUnsynced());
   }
 }
 
+TEST_F(SyncBackupManagerTest, FailToInitialize) {
+  // Test graceful shutdown on initialization failure.
+  scoped_ptr<SyncBackupManager> manager(new SyncBackupManager);
+  InitManager(manager.get(), STORAGE_INVALID);
+}
+
 }  // anonymous namespace
 
 }  // namespace syncer
diff --git a/sync/internal_api/sync_rollback_manager.cc b/sync/internal_api/sync_rollback_manager.cc
index 84367b0..c5a6f75 100644
--- a/sync/internal_api/sync_rollback_manager.cc
+++ b/sync/internal_api/sync_rollback_manager.cc
@@ -41,28 +41,22 @@
       ReportUnrecoverableErrorFunction
           report_unrecoverable_error_function,
       CancelationSignal* cancelation_signal) {
-  SyncRollbackManagerBase::Init(database_location, event_handler,
-                                sync_server_and_path, sync_server_port,
-                                use_ssl, post_factory.Pass(),
-                                workers, extensions_activity, change_delegate,
-                                credentials, invalidator_client_id,
-                                restored_key_for_bootstrapping,
-                                restored_keystore_key_for_bootstrapping,
-                                internal_components_factory, encryptor,
-                                unrecoverable_error_handler.Pass(),
-                                report_unrecoverable_error_function,
-                                cancelation_signal);
+  if (SyncRollbackManagerBase::InitInternal(
+          database_location,
+          internal_components_factory,
+          unrecoverable_error_handler.Pass(),
+          report_unrecoverable_error_function)) {
+    change_delegate_ = change_delegate;
 
-  change_delegate_ = change_delegate;
+    for (size_t i = 0; i < workers.size(); ++i) {
+      ModelSafeGroup group = workers[i]->GetModelSafeGroup();
+      CHECK(workers_.find(group) == workers_.end());
+      workers_[group] = workers[i];
+    }
 
-  for (size_t i = 0; i < workers.size(); ++i) {
-    ModelSafeGroup group = workers[i]->GetModelSafeGroup();
-    CHECK(workers_.find(group) == workers_.end());
-    workers_[group] = workers[i];
+    rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes();
+    rollback_ready_types_.RetainAll(BackupTypes());
   }
-
-  rollback_ready_types_ = GetUserShare()->directory->InitialSyncEndedTypes();
-  rollback_ready_types_.RetainAll(BackupTypes());
 }
 
 void SyncRollbackManager::StartSyncingNormally(
diff --git a/sync/internal_api/sync_rollback_manager_base.cc b/sync/internal_api/sync_rollback_manager_base.cc
index ade0422..338f5af 100644
--- a/sync/internal_api/sync_rollback_manager_base.cc
+++ b/sync/internal_api/sync_rollback_manager_base.cc
@@ -15,8 +15,8 @@
 namespace {
 
 // Permanent bookmark folders as defined in bookmark_model_associator.cc.
+// No mobile bookmarks because they only exists with sync enabled.
 const char kBookmarkBarTag[] = "bookmark_bar";
-const char kMobileBookmarksTag[] = "synced_bookmarks";
 const char kOtherBookmarksTag[] = "other_bookmarks";
 
 class DummyEntryptionHandler : public syncer::SyncEncryptionHandler {
@@ -43,41 +43,29 @@
 SyncRollbackManagerBase::SyncRollbackManagerBase()
     : report_unrecoverable_error_function_(NULL),
       weak_ptr_factory_(this),
-      dummy_handler_(new DummyEntryptionHandler) {
+      dummy_handler_(new DummyEntryptionHandler),
+      initialized_(false) {
 }
 
 SyncRollbackManagerBase::~SyncRollbackManagerBase() {
 }
 
-void SyncRollbackManagerBase::Init(
-      const base::FilePath& database_location,
-      const WeakHandle<JsEventHandler>& event_handler,
-      const std::string& sync_server_and_path,
-      int sync_server_port,
-      bool use_ssl,
-      scoped_ptr<HttpPostProviderFactory> post_factory,
-      const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
-      ExtensionsActivity* extensions_activity,
-      SyncManager::ChangeDelegate* change_delegate,
-      const SyncCredentials& credentials,
-      const std::string& invalidator_client_id,
-      const std::string& restored_key_for_bootstrapping,
-      const std::string& restored_keystore_key_for_bootstrapping,
-      InternalComponentsFactory* internal_components_factory,
-      Encryptor* encryptor,
-      scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
-      ReportUnrecoverableErrorFunction
-          report_unrecoverable_error_function,
-      CancelationSignal* cancelation_signal) {
+bool SyncRollbackManagerBase::InitInternal(
+    const base::FilePath& database_location,
+    InternalComponentsFactory* internal_components_factory,
+    scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
+    ReportUnrecoverableErrorFunction report_unrecoverable_error_function) {
   unrecoverable_error_handler_ = unrecoverable_error_handler.Pass();
   report_unrecoverable_error_function_ = report_unrecoverable_error_function;
 
   if (!InitBackupDB(database_location, internal_components_factory)) {
     NotifyInitializationFailure();
-    return;
+    return false;
   }
 
+  initialized_ = true;
   NotifyInitializationSuccess();
+  return true;
 }
 
 ModelTypeSet SyncRollbackManagerBase::InitialSyncEndedTypes() {
@@ -118,7 +106,6 @@
     if (InitTypeRootNode(type.Get())) {
       if (type.Get() == BOOKMARKS) {
         InitBookmarkFolder(kBookmarkBarTag);
-        InitBookmarkFolder(kMobileBookmarksTag);
         InitBookmarkFolder(kOtherBookmarksTag);
       }
     }
@@ -151,10 +138,11 @@
 }
 
 void SyncRollbackManagerBase::ShutdownOnSyncThread() {
-  if (share_.directory) {
+  if (initialized_) {
     SaveChanges();
     share_.directory->Close();
     share_.directory.reset();
+    initialized_ = false;
   }
 }
 
@@ -227,7 +215,7 @@
       OnInitializationComplete(
           MakeWeakHandle(base::WeakPtr<JsBackend>()),
           MakeWeakHandle(base::WeakPtr<DataTypeDebugInfoListener>()),
-          false, InitialSyncEndedTypes()));
+          false, ModelTypeSet()));
 }
 
 std::string SyncRollbackManagerBase::GetOwnerName() const {
diff --git a/sync/internal_api/sync_rollback_manager_base.h b/sync/internal_api/sync_rollback_manager_base.h
index 6b4153e..fce980b 100644
--- a/sync/internal_api/sync_rollback_manager_base.h
+++ b/sync/internal_api/sync_rollback_manager_base.h
@@ -35,26 +35,6 @@
   virtual ~SyncRollbackManagerBase();
 
   // SyncManager implementation.
-  virtual void Init(
-      const base::FilePath& database_location,
-      const WeakHandle<JsEventHandler>& event_handler,
-      const std::string& sync_server_and_path,
-      int sync_server_port,
-      bool use_ssl,
-      scoped_ptr<HttpPostProviderFactory> post_factory,
-      const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
-      ExtensionsActivity* extensions_activity,
-      SyncManager::ChangeDelegate* change_delegate,
-      const SyncCredentials& credentials,
-      const std::string& invalidator_client_id,
-      const std::string& restored_key_for_bootstrapping,
-      const std::string& restored_keystore_key_for_bootstrapping,
-      InternalComponentsFactory* internal_components_factory,
-      Encryptor* encryptor,
-      scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
-      ReportUnrecoverableErrorFunction
-          report_unrecoverable_error_function,
-      CancelationSignal* cancelation_signal) OVERRIDE;
   virtual ModelTypeSet InitialSyncEndedTypes() OVERRIDE;
   virtual ModelTypeSet GetTypesWithEmptyProgressMarkerToken(
       ModelTypeSet types) OVERRIDE;
@@ -115,6 +95,13 @@
  protected:
   ObserverList<SyncManager::Observer>* GetObservers();
 
+  // Initialize sync backup DB.
+  bool InitInternal(
+      const base::FilePath& database_location,
+      InternalComponentsFactory* internal_components_factory,
+      scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
+      ReportUnrecoverableErrorFunction report_unrecoverable_error_function);
+
   virtual void RegisterDirectoryTypeDebugInfoObserver(
       syncer::TypeDebugInfoObserver* observer) OVERRIDE;
   virtual void UnregisterDirectoryTypeDebugInfoObserver(
@@ -123,6 +110,10 @@
       syncer::TypeDebugInfoObserver* observer) OVERRIDE;
   virtual void RequestEmitDebugInfo() OVERRIDE;
 
+  bool initialized() const {
+    return initialized_;
+  }
+
  private:
   void NotifyInitializationSuccess();
   void NotifyInitializationFailure();
@@ -144,6 +135,8 @@
 
   scoped_ptr<SyncEncryptionHandler> dummy_handler_;
 
+  bool initialized_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncRollbackManagerBase);
 };
 
diff --git a/sync/internal_api/sync_rollback_manager_base_unittest.cc b/sync/internal_api/sync_rollback_manager_base_unittest.cc
index 79075d2..1d4c2de 100644
--- a/sync/internal_api/sync_rollback_manager_base_unittest.cc
+++ b/sync/internal_api/sync_rollback_manager_base_unittest.cc
@@ -18,6 +18,34 @@
   EXPECT_TRUE(success);
 }
 
+class SyncTestRollbackManager : public SyncRollbackManagerBase {
+ public:
+  virtual void Init(
+      const base::FilePath& database_location,
+      const WeakHandle<JsEventHandler>& event_handler,
+      const std::string& sync_server_and_path,
+      int sync_server_port,
+      bool use_ssl,
+      scoped_ptr<HttpPostProviderFactory> post_factory,
+      const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
+      ExtensionsActivity* extensions_activity,
+      ChangeDelegate* change_delegate,
+      const SyncCredentials& credentials,
+      const std::string& invalidator_client_id,
+      const std::string& restored_key_for_bootstrapping,
+      const std::string& restored_keystore_key_for_bootstrapping,
+      InternalComponentsFactory* internal_components_factory,
+      Encryptor* encryptor,
+      scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
+      ReportUnrecoverableErrorFunction report_unrecoverable_error_function,
+      CancelationSignal* cancelation_signal) OVERRIDE {
+    SyncRollbackManagerBase::InitInternal(database_location,
+                                          internal_components_factory,
+                                          unrecoverable_error_handler.Pass(),
+                                          report_unrecoverable_error_function);
+  }
+};
+
 class SyncRollbackManagerBaseTest : public testing::Test {
  protected:
   virtual void SetUp() OVERRIDE {
@@ -32,7 +60,7 @@
                   NULL, NULL);
   }
 
-  SyncRollbackManagerBase manager_;
+  SyncTestRollbackManager manager_;
   base::MessageLoop loop_;    // Needed for WeakHandle
 };
 
@@ -58,7 +86,7 @@
   EXPECT_EQ(BaseNode::INIT_OK,
             bookmark_bar.InitByTagLookupForBookmarks("bookmark_bar"));
   ReadNode bookmark_mobile(&trans);
-  EXPECT_EQ(BaseNode::INIT_OK,
+  EXPECT_EQ(BaseNode::INIT_FAILED_ENTRY_NOT_GOOD,
             bookmark_mobile.InitByTagLookupForBookmarks("synced_bookmarks"));
   ReadNode bookmark_other(&trans);
   EXPECT_EQ(BaseNode::INIT_OK,
diff --git a/sync/internal_api/sync_rollback_manager_unittest.cc b/sync/internal_api/sync_rollback_manager_unittest.cc
index d66ee06..11f875f 100644
--- a/sync/internal_api/sync_rollback_manager_unittest.cc
+++ b/sync/internal_api/sync_rollback_manager_unittest.cc
@@ -5,6 +5,7 @@
 #include "sync/internal_api/sync_rollback_manager.h"
 
 #include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
 #include "sync/internal_api/public/read_node.h"
 #include "sync/internal_api/public/read_transaction.h"
 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
@@ -76,9 +77,9 @@
                void(const sessions::SyncSessionSnapshot&));
   MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));
   MOCK_METHOD4(OnInitializationComplete,
-      void(const WeakHandle<JsBackend>&,
-           const WeakHandle<DataTypeDebugInfoListener>&,
-           bool, ModelTypeSet));
+               void(const WeakHandle<JsBackend>&,
+                    const WeakHandle<DataTypeDebugInfoListener>&,
+                    bool, ModelTypeSet));
   MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));
   MOCK_METHOD1(OnMigrationRequested, void(ModelTypeSet));;
   MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));
@@ -100,11 +101,19 @@
   }
 
   void InitManager(SyncManager* manager, ModelTypeSet types,
-                   TestChangeDelegate* delegate) {
+                   TestChangeDelegate* delegate, StorageOption storage_option) {
+    manager_ = manager;
+    types_ = types;
+
+    EXPECT_CALL(*this, OnInitializationComplete(_, _, _, _))
+        .WillOnce(WithArgs<2>(Invoke(this,
+                                     &SyncRollbackManagerTest::HandleInit)));
+
     manager->AddObserver(this);
     TestInternalComponentsFactory factory(InternalComponentsFactory::Switches(),
-                                          STORAGE_ON_DISK);
+                                          storage_option);
 
+    base::RunLoop run_loop;
     manager->Init(temp_dir_.path(),
                   MakeWeakHandle(base::WeakPtr<JsEventHandler>()),
                   "", 0, true, scoped_ptr<HttpPostProviderFactory>().Pass(),
@@ -113,21 +122,16 @@
                   NULL, delegate, SyncCredentials(), "", "", "", &factory,
                   NULL, scoped_ptr<UnrecoverableErrorHandler>().Pass(),
                   NULL, NULL);
-    manager->ConfigureSyncer(
-        CONFIGURE_REASON_NEW_CLIENT,
-        types,
-        ModelTypeSet(), ModelTypeSet(), ModelTypeSet(), ModelSafeRoutingInfo(),
-        base::Bind(&SyncRollbackManagerTest::OnConfigDone,
-                   base::Unretained(this), true),
-        base::Bind(&SyncRollbackManagerTest::OnConfigDone,
-                   base::Unretained(this), false));
+    loop_.PostTask(FROM_HERE, run_loop.QuitClosure());
+    run_loop.Run();
   }
 
   // Create and persist an entry by unique tag in DB.
   void PrepopulateDb(ModelType type, const std::string& client_tag) {
     SyncBackupManager backup_manager;
     TestChangeDelegate delegate;
-    InitManager(&backup_manager, ModelTypeSet(type), &delegate);
+    InitManager(&backup_manager, ModelTypeSet(type), &delegate,
+                STORAGE_ON_DISK);
     CreateEntry(backup_manager.GetUserShare(), type, client_tag);
     backup_manager.ShutdownOnSyncThread();
   }
@@ -140,9 +144,34 @@
     return BaseNode::INIT_OK == node.InitByClientTagLookup(type, client_tag);
   }
 
+ private:
+  void ConfigureSyncer() {
+    manager_->ConfigureSyncer(
+          CONFIGURE_REASON_NEW_CLIENT,
+          types_,
+          ModelTypeSet(), ModelTypeSet(), ModelTypeSet(),
+          ModelSafeRoutingInfo(),
+          base::Bind(&SyncRollbackManagerTest::OnConfigDone,
+                     base::Unretained(this), true),
+          base::Bind(&SyncRollbackManagerTest::OnConfigDone,
+                     base::Unretained(this), false));
+  }
+
+  void HandleInit(bool success) {
+    if (success) {
+      loop_.PostTask(FROM_HERE,
+                     base::Bind(&SyncRollbackManagerTest::ConfigureSyncer,
+                                base::Unretained(this)));
+    } else {
+      manager_->ShutdownOnSyncThread();
+    }
+  }
+
   base::ScopedTempDir temp_dir_;
   scoped_refptr<ModelSafeWorker> worker_;
   base::MessageLoop loop_;    // Needed for WeakHandle
+  SyncManager* manager_;
+  ModelTypeSet types_;
 };
 
 bool IsRollbackDoneAction(SyncProtocolError e) {
@@ -154,7 +183,8 @@
 
   TestChangeDelegate delegate;
   SyncRollbackManager rollback_manager;
-  InitManager(&rollback_manager, ModelTypeSet(PREFERENCES), &delegate);
+  InitManager(&rollback_manager, ModelTypeSet(PREFERENCES), &delegate,
+              STORAGE_ON_DISK);
 
   // Simulate a new entry added during type initialization.
   int64 new_pref_id =
@@ -177,7 +207,8 @@
 
   TestChangeDelegate delegate;
   SyncRollbackManager rollback_manager;
-  InitManager(&rollback_manager, ModelTypeSet(PREFERENCES, APPS), &delegate);
+  InitManager(&rollback_manager, ModelTypeSet(PREFERENCES, APPS), &delegate,
+              STORAGE_ON_DISK);
 
   // Simulate new entry added during type initialization.
   int64 new_pref_id =
@@ -204,7 +235,8 @@
   TestChangeDelegate delegate;
   scoped_ptr<SyncRollbackManager> rollback_manager(
       new SyncRollbackManager);
-  InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate);
+  InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate,
+              STORAGE_ON_DISK);
 
   // Simulate a new entry added during type initialization.
   CreateEntry(rollback_manager->GetUserShare(), PREFERENCES, "pref2");
@@ -214,11 +246,20 @@
 
   // Verify new entry was not persisted.
   rollback_manager.reset(new SyncRollbackManager);
-  InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate);
+  InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), &delegate,
+              STORAGE_ON_DISK);
   EXPECT_FALSE(VerifyEntry(rollback_manager->GetUserShare(), PREFERENCES,
                            "pref2"));
 }
 
+TEST_F(SyncRollbackManagerTest, OnInitializationFailure) {
+  // Test graceful shutdown on initialization failure.
+  scoped_ptr<SyncRollbackManager> rollback_manager(
+      new SyncRollbackManager);
+  InitManager(rollback_manager.get(), ModelTypeSet(PREFERENCES), NULL,
+              STORAGE_ON_DISK);
+}
+
 }  // anonymous namespace
 
 }  // namespace syncer
diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc
index ad107b1..be489b2 100644
--- a/sync/syncable/directory.cc
+++ b/sync/syncable/directory.cc
@@ -1446,5 +1446,10 @@
   }
 }
 
+void Directory::UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry) {
+  CHECK(trans);
+  entry->kernel_->clear_dirty(&kernel_->dirty_metahandles);
+}
+
 }  // namespace syncable
 }  // namespace syncer
diff --git a/sync/syncable/directory.h b/sync/syncable/directory.h
index f7dd44e..2830eec 100644
--- a/sync/syncable/directory.h
+++ b/sync/syncable/directory.h
@@ -19,6 +19,7 @@
 #include "sync/internal_api/public/util/report_unrecoverable_error_function.h"
 #include "sync/internal_api/public/util/weak_handle.h"
 #include "sync/syncable/dir_open_result.h"
+#include "sync/syncable/entry.h"
 #include "sync/syncable/entry_kernel.h"
 #include "sync/syncable/metahandle_set.h"
 #include "sync/syncable/parent_child_index.h"
@@ -404,6 +405,11 @@
       const sync_pb::AttachmentIdProto& attachment_id_proto,
       Metahandles* result);
 
+  // Change entry to not dirty. Used in special case when we don't want to
+  // persist modified entry on disk. e.g. SyncBackupManager uses this to
+  // preserve sync preferences in DB on disk.
+  void UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry);
+
  protected:  // for friends, mainly used by Entry constructors
   virtual EntryKernel* GetEntryByHandle(int64 handle);
   virtual EntryKernel* GetEntryByHandle(int64 metahandle,
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 34af7b6..cf3e4f5 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -5145,6 +5145,11 @@
   </summary>
 </histogram>
 
+<histogram name="Enterprise.EnrollmentRecovery" enum="EnterpriseEnrollmentType">
+  <owner>tnagel@chromium.org</owner>
+  <summary>Events related to Chrome OS enterprise enrollment recovery.</summary>
+</histogram>
+
 <histogram name="Enterprise.IOSPolicies">
   <owner>joaodasilva@chromium.org</owner>
   <summary>
@@ -20819,6 +20824,17 @@
   </summary>
 </histogram>
 
+<histogram name="Plugin.AvailabilityStatus.WidevineCdm"
+    enum="PluginAvailabilityStatus">
+  <owner>xhwang@chromium.org</owner>
+  <summary>
+    The availability status of Widevine CDM. In normal cases, this is reported
+    per render process if EME API is used. This is not reported if EME API is
+    not used. This could be reported multiple times per render process until
+    PLUGIN_AVAILABLE is reported (which should be a rare case).
+  </summary>
+</histogram>
+
 <histogram name="Plugin.FlashNavigateUsage" enum="FlashNavigateUsageType">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Record usage of PPB_Flash.Navigate() Pepper API.</summary>
@@ -35258,6 +35274,10 @@
   <int value="23" label="Domain mismatch">
     Enrollment failed because the device belongs to a different domain.
   </int>
+  <int value="24" label="Triggered">
+    Enrollment has been triggered, the credential screen has been shown.
+  </int>
+  <int value="25" label="Retried">The user retried to submit credentials.</int>
 </enum>
 
 <enum name="EnterprisePolicies" type="int">
@@ -42233,6 +42253,12 @@
   <int value="16" label="I/O"/>
 </enum>
 
+<enum name="PluginAvailabilityStatus" type="int">
+  <int value="0" label="PLUGIN_NOT_REGISTERED"/>
+  <int value="1" label="PLUGIN_AVAILABLE"/>
+  <int value="2" label="PLUGIN_DISABLED"/>
+</enum>
+
 <enum name="PluginLoadResult" type="int">
   <int value="0" label="LOAD_SUCCESS"/>
   <int value="1" label="LOAD_FAILED"/>
diff --git a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
index 894376c..d9faa0f 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
@@ -5,6 +5,7 @@
 package org.chromium.ui;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.view.View;
 import android.view.View.MeasureSpec;
 import android.view.View.OnLayoutChangeListener;
@@ -30,6 +31,7 @@
     private float mAnchorY;
     private OnLayoutChangeListener mLayoutChangeListener;
     private PopupWindow.OnDismissListener mOnDismissListener;
+    ListAdapter mAdapter;
 
     /**
      * Creates an DropdownPopupWindow with specified parameters.
@@ -89,21 +91,32 @@
     }
 
     @Override
+    public void setAdapter(ListAdapter adapter) {
+        mAdapter = adapter;
+        super.setAdapter(adapter);
+    }
+
+    @Override
     public void show() {
         // An ugly hack to keep the popup from expanding on top of the keyboard.
         setInputMethodMode(INPUT_METHOD_NEEDED);
-        super.show();
-        getListView().setDividerHeight(0);
         int contentWidth = measureContentWidth();
         float contentWidthInDip = contentWidth /
                 mContext.getResources().getDisplayMetrics().density;
         if (contentWidthInDip > mAnchorWidth) {
             setContentWidth(contentWidth);
+            final Rect displayFrame = new Rect();
+            mAnchorView.getWindowVisibleDisplayFrame(displayFrame);
+            if (getWidth() > displayFrame.width()) {
+                setWidth(displayFrame.width());
+            }
         } else {
             setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
         }
         mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth,
                 mAnchorHeight);
+        super.show();
+        getListView().setDividerHeight(0);
     }
 
     @Override
@@ -118,13 +131,12 @@
     private int measureContentWidth() {
         int maxWidth = 0;
         View itemView = null;
-        final ListAdapter adapter = getListView().getAdapter();
-        if (adapter == null)
+        if (mAdapter == null)
           return 0;
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
-        for (int i = 0; i < adapter.getCount(); i++) {
-            itemView = adapter.getView(i, itemView, null);
+        for (int i = 0; i < mAdapter.getCount(); i++) {
+            itemView = mAdapter.getView(i, itemView, null);
             LinearLayout.LayoutParams params =
                     new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                             LinearLayout.LayoutParams.WRAP_CONTENT);
diff --git a/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java b/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java
new file mode 100644
index 0000000..f95d855
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java
@@ -0,0 +1,163 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.ui.interpolators;
+
+import android.view.animation.Interpolator;
+
+/**
+ * A pre-baked bezier-curved interpolator for quantum-paper transitions.
+ * TODO(dtrainor): Move to the API Compatability version iff that supports the curves we need and
+ * once we move to that SDK.
+ */
+public class BakedBezierInterpolator implements Interpolator {
+    /**
+     * Lookup table values.
+     * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+     * P0 (0.0, 0.0)
+     * P1 (0.4, 0.0)
+     * P2 (0.2, 1.0)
+     * P3 (1.0, 1.0)
+     *
+     * Values sampled with x at regular intervals between 0 and 1.
+     */
+    private static final float[] TRANSFORM_VALUES = new float[] {
+        0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
+        0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
+        0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
+        0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
+        0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
+        0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
+        0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
+        0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
+        0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
+        0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+    };
+
+    /**
+     * Lookup table values.
+     * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+     * P0 (0.0, 0.0)
+     * P1 (0.4, 0.0)
+     * P2 (1.0, 1.0)
+     * P3 (1.0, 1.0)
+     *
+     * Values sampled with x at regular intervals between 0 and 1.
+     */
+    private static final float[] FADE_OUT_VALUES = new float[] {
+        0.0f, 0.0002f, 0.0008f, 0.0019f, 0.0032f, 0.0049f, 0.0069f, 0.0093f, 0.0119f, 0.0149f,
+        0.0182f, 0.0218f, 0.0257f, 0.0299f, 0.0344f, 0.0392f, 0.0443f, 0.0496f, 0.0552f, 0.0603f,
+        0.0656f, 0.0719f, 0.0785f, 0.0853f, 0.0923f, 0.0986f, 0.1051f, 0.1128f, 0.1206f, 0.1287f,
+        0.1359f, 0.1433f, 0.1519f, 0.1607f, 0.1696f, 0.1776f, 0.1857f, 0.1952f, 0.2048f, 0.2145f,
+        0.2232f, 0.2319f, 0.2421f, 0.2523f, 0.2627f, 0.2733f, 0.2826f, 0.2919f, 0.3027f, 0.3137f,
+        0.3247f, 0.3358f, 0.3469f, 0.3582f, 0.3695f, 0.3809f, 0.3924f, 0.4039f, 0.4154f, 0.427f,
+        0.4386f, 0.4503f, 0.4619f, 0.4751f, 0.4883f, 0.5f, 0.5117f, 0.5264f, 0.5381f, 0.5497f,
+        0.5643f, 0.5759f, 0.5904f, 0.6033f, 0.6162f, 0.6305f, 0.6446f, 0.6587f, 0.6698f, 0.6836f,
+        0.7f, 0.7134f, 0.7267f, 0.7425f, 0.7554f, 0.7706f, 0.7855f, 0.8f, 0.8143f, 0.8281f, 0.8438f,
+        0.8588f, 0.8733f, 0.8892f, 0.9041f, 0.9215f, 0.9344f, 0.9518f, 0.9667f, 0.9826f, 0.9993f
+    };
+
+    /**
+     * Lookup table values.
+     * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+     * P0 (0.0, 0.0)
+     * P1 (0.0, 0.0)
+     * P2 (0.2, 1.0)
+     * P3 (1.0, 1.0)
+     *
+     * Values sampled with x at regular intervals between 0 and 1.
+     */
+    private static final float[] FADE_IN_VALUES = new float[] {
+        0.0029f, 0.043f, 0.0785f, 0.1147f, 0.1476f, 0.1742f, 0.2024f, 0.2319f, 0.2575f, 0.2786f,
+        0.3055f, 0.3274f, 0.3498f, 0.3695f, 0.3895f, 0.4096f, 0.4299f, 0.4474f, 0.4649f, 0.4824f,
+        0.5f, 0.5176f, 0.5322f, 0.5468f, 0.5643f, 0.5788f, 0.5918f, 0.6048f, 0.6191f, 0.6333f,
+        0.6446f, 0.6573f, 0.6698f, 0.6808f, 0.6918f, 0.704f, 0.7148f, 0.7254f, 0.7346f, 0.7451f,
+        0.7554f, 0.7655f, 0.7731f, 0.783f, 0.7916f, 0.8f, 0.8084f, 0.8166f, 0.8235f, 0.8315f,
+        0.8393f, 0.8459f, 0.8535f, 0.8599f, 0.8672f, 0.8733f, 0.8794f, 0.8853f, 0.8911f, 0.8967f,
+        0.9023f, 0.9077f, 0.9121f, 0.9173f, 0.9224f, 0.9265f, 0.9313f, 0.9352f, 0.9397f, 0.9434f,
+        0.9476f, 0.9511f, 0.9544f, 0.9577f, 0.9614f, 0.9644f, 0.9673f, 0.9701f, 0.9727f, 0.9753f,
+        0.9777f, 0.98f, 0.9818f, 0.9839f, 0.9859f, 0.9877f, 0.9891f, 0.9907f, 0.9922f, 0.9933f,
+        0.9946f, 0.9957f, 0.9966f, 0.9974f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+    };
+
+    /**
+     * Lookup table values.
+     * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+     * P0 (0.0, 0.0)
+     * P1 (0.0, 0.84)
+     * P2 (0.13, 0.99)
+     * P3 (1.0, 1.0)
+     */
+    private static final float[] TRANSFORM_FOLLOW_THROUGH_VALUES = new float[] {
+        0.0767f, 0.315f, 0.4173f, 0.484f, 0.5396f, 0.5801f, 0.6129f, 0.644f, 0.6687f, 0.6876f,
+        0.7102f, 0.7276f, 0.7443f, 0.7583f, 0.7718f, 0.7849f, 0.7975f, 0.8079f, 0.8179f, 0.8276f,
+        0.8355f, 0.8446f, 0.8519f, 0.859f, 0.8659f, 0.8726f, 0.8791f, 0.8841f, 0.8902f, 0.8949f,
+        0.9001f, 0.9051f, 0.9094f, 0.9136f, 0.9177f, 0.9217f, 0.925f, 0.9283f, 0.9319f, 0.9355f,
+        0.938f, 0.9413f, 0.9437f, 0.9469f, 0.9491f, 0.9517f, 0.9539f, 0.9563f, 0.9583f, 0.9603f,
+        0.9622f, 0.9643f, 0.9661f, 0.9679f, 0.9693f, 0.9709f, 0.9725f, 0.974f, 0.9753f, 0.9767f,
+        0.9779f, 0.9792f, 0.9803f, 0.9816f, 0.9826f, 0.9835f, 0.9845f, 0.9854f, 0.9863f, 0.9872f,
+        0.988f, 0.9888f, 0.9895f, 0.9903f, 0.991f, 0.9917f, 0.9922f, 0.9928f, 0.9934f, 0.9939f,
+        0.9944f, 0.9948f, 0.9953f, 0.9957f, 0.9962f, 0.9965f, 0.9969f, 0.9972f, 0.9975f, 0.9978f,
+        0.9981f, 0.9984f, 0.9986f, 0.9989f, 0.9991f, 0.9992f, 0.9994f, 0.9996f, 0.9997f, 0.9999f,
+        1.0f
+    };
+
+    /**
+     * 0.4 to 0.2 bezier curve.  Should be used for general movement.
+     */
+    public static final BakedBezierInterpolator TRANSFORM_CURVE =
+            new BakedBezierInterpolator(TRANSFORM_VALUES);
+
+    /**
+     * 0.4 to 1.0 bezier curve.  Should be used for fading out.
+     */
+    public static final BakedBezierInterpolator FADE_OUT_CURVE =
+            new BakedBezierInterpolator(FADE_OUT_VALUES);
+
+    /**
+     * 0.0 to 0.2 bezier curve.  Should be used for fading in.
+     */
+    public static final BakedBezierInterpolator FADE_IN_CURVE =
+            new BakedBezierInterpolator(FADE_IN_VALUES);
+
+    /**
+     * 0.0 to 0.13 by 0.84 to 0.99 bezier curve.  Should be used for very quick transforms.
+     */
+    public static final BakedBezierInterpolator TRANSFORM_FOLLOW_THROUGH_CURVE =
+            new BakedBezierInterpolator(TRANSFORM_FOLLOW_THROUGH_VALUES);
+
+    private final float[] mValues;
+    private final float mStepSize;
+
+    /**
+     * Use the INSTANCE variable instead of instantiating.
+     */
+    private BakedBezierInterpolator(float[] values) {
+        super();
+        mValues = values;
+        mStepSize = 1.f / (mValues.length - 1);
+    }
+
+    @Override
+    public float getInterpolation(float input) {
+        if (input >= 1.0f) {
+            return 1.0f;
+        }
+
+        if (input <= 0f) {
+            return 0f;
+        }
+
+        int position = Math.min(
+                (int)(input * (mValues.length - 1)),
+                mValues.length - 2);
+
+        float quantized = position * mStepSize;
+        float difference = input - quantized;
+        float weight = difference / mStepSize;
+
+        return mValues[position] + weight * (mValues[position + 1] - mValues[position]);
+    }
+
+}
\ No newline at end of file
diff --git a/ui/display/chromeos/touchscreen_delegate_impl.cc b/ui/display/chromeos/touchscreen_delegate_impl.cc
index 5311a82..dc60e3f 100644
--- a/ui/display/chromeos/touchscreen_delegate_impl.cc
+++ b/ui/display/chromeos/touchscreen_delegate_impl.cc
@@ -23,7 +23,38 @@
     std::vector<DisplayConfigurator::DisplayState>* displays) {
   std::set<int> no_match_touchscreen;
   std::vector<TouchscreenDevice> devices = touch_device_manager_->GetDevices();
+
+  int internal_touchscreen = -1;
   for (size_t i = 0; i < devices.size(); ++i) {
+    if (devices[i].is_internal) {
+      internal_touchscreen = i;
+      break;
+    }
+  }
+
+  DisplayConfigurator::DisplayState* internal_state = NULL;
+  for (size_t i = 0; i < displays->size(); ++i) {
+    DisplayConfigurator::DisplayState* state = &(*displays)[i];
+    if (state->display->type() == DISPLAY_CONNECTION_TYPE_INTERNAL &&
+        state->display->native_mode() &&
+        state->touch_device_id == 0) {
+      internal_state = state;
+      break;
+    }
+  }
+
+  if (internal_state && internal_touchscreen >= 0) {
+    internal_state->touch_device_id = devices[internal_touchscreen].id;
+    VLOG(2) << "Found internal touchscreen for internal display "
+            << internal_state->display->display_id() << " touch_device_id "
+            << internal_state->touch_device_id << " size "
+            << devices[internal_touchscreen].size.ToString();
+  }
+
+  for (size_t i = 0; i < devices.size(); ++i) {
+    if (internal_state &&
+        internal_state->touch_device_id == devices[i].id)
+      continue;
     bool found_mapping = false;
     for (size_t j = 0; j < displays->size(); ++j) {
       DisplayConfigurator::DisplayState* state = &(*displays)[j];
diff --git a/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc b/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc
index b41fbdb..9e80712 100644
--- a/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc
+++ b/ui/display/chromeos/touchscreen_delegate_impl_unittest.cc
@@ -48,8 +48,9 @@
     delegate_.reset(new TouchscreenDelegateImpl(
         scoped_ptr<TouchscreenDeviceManager>(device_manager_)));
 
-    // Internal display. Must not be matched to a touch screen unless the size
-    // matches.
+    // Internal display will always match to internal touchscreen. If internal
+    // touchscreen can't be detected, it is then associated to a touch screen
+    // with matching size.
     TestDisplaySnapshot* snapshot = new TestDisplaySnapshot();
     DisplayMode* mode = new DisplayMode(gfx::Size(1920, 1080), false, 60.0);
     snapshot->set_type(DISPLAY_CONNECTION_TYPE_INTERNAL);
@@ -110,8 +111,8 @@
 }
 
 TEST_F(TouchscreenDelegateImplTest, OneToOneMapping) {
-  device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(800, 600)));
-  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768)));
+  device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(800, 600), false));
+  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768), false));
 
   std::vector<DisplayConfigurator::DisplayState> display_states =
       GetDisplayStates();
@@ -124,7 +125,7 @@
 }
 
 TEST_F(TouchscreenDelegateImplTest, MapToCorrectDisplaySize) {
-  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768)));
+  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1024, 768), false));
 
   std::vector<DisplayConfigurator::DisplayState> display_states =
       GetDisplayStates();
@@ -137,8 +138,8 @@
 }
 
 TEST_F(TouchscreenDelegateImplTest, MapWhenSizeDiffersByOne) {
-  device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(801, 600)));
-  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1023, 768)));
+  device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(801, 600), false));
+  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(1023, 768), false));
 
   std::vector<DisplayConfigurator::DisplayState> display_states =
       GetDisplayStates();
@@ -151,8 +152,8 @@
 }
 
 TEST_F(TouchscreenDelegateImplTest, MapWhenSizesDoNotMatch) {
-  device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(1022, 768)));
-  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(802, 600)));
+  device_manager_->AddDevice(TouchscreenDevice(1, gfx::Size(1022, 768), false));
+  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(802, 600), false));
 
   std::vector<DisplayConfigurator::DisplayState> display_states =
       GetDisplayStates();
@@ -164,4 +165,20 @@
   EXPECT_EQ(2, display_states[3].touch_device_id);
 }
 
+TEST_F(TouchscreenDelegateImplTest, MapInternalTouchscreen) {
+  device_manager_->AddDevice(
+      TouchscreenDevice(1, gfx::Size(1920, 1080), false));
+  device_manager_->AddDevice(TouchscreenDevice(2, gfx::Size(9999, 888), true));
+
+  std::vector<DisplayConfigurator::DisplayState> display_states =
+      GetDisplayStates();
+  delegate_->AssociateTouchscreens(&display_states);
+
+  // Internal touchscreen is always mapped to internal display.
+  EXPECT_EQ(2, display_states[0].touch_device_id);
+  EXPECT_EQ(1, display_states[1].touch_device_id);
+  EXPECT_EQ(TouchscreenDevice::kInvalidId, display_states[2].touch_device_id);
+  EXPECT_EQ(TouchscreenDevice::kInvalidId, display_states[3].touch_device_id);
+}
+
 }  // namespace ui
diff --git a/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc b/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
index 6c8137b..f613532 100644
--- a/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
+++ b/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
@@ -9,9 +9,88 @@
 
 #include <cmath>
 #include <set>
+#include <string>
+#include <vector>
 
+#include "base/command_line.h"
+#include "base/files/file_enumerator.h"
+#include "base/logging.h"
+#include "base/process/launch.h"
+#include "base/strings/string_util.h"
+#include "base/sys_info.h"
 #include "ui/gfx/x/x11_types.h"
 
+namespace {
+
+// We consider the touchscreen to be internal if it is an I2c device.
+// With the device id, we can query X to get the device's dev input
+// node eventXXX. Then we search all the dev input nodes registered
+// by I2C devices to see if we can find eventXXX.
+bool IsTouchscreenInternal(XDisplay* dpy, int device_id) {
+  using base::FileEnumerator;
+  using base::FilePath;
+
+  if (!base::SysInfo::IsRunningOnChromeOS())
+    return false;
+
+  // Input device has a property "Device Node" pointing to its dev input node,
+  // e.g.   Device Node (250): "/dev/input/event8"
+  Atom device_node = XInternAtom(dpy, "Device Node", False);
+  if (device_node == None)
+    return false;
+
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems, bytes_after;
+  unsigned char* data;
+  XDevice* dev = XOpenDevice(dpy, device_id);
+  if (!dev)
+    return false;
+
+  if (XGetDeviceProperty(dpy, dev, device_node, 0, 1000, False,
+                         AnyPropertyType, &actual_type, &actual_format,
+                         &nitems, &bytes_after, &data) != Success) {
+    XCloseDevice(dpy, dev);
+    return false;
+  }
+  base::FilePath dev_node_path(reinterpret_cast<char*>(data));
+  XFree(data);
+  XCloseDevice(dpy, dev);
+
+  std::string event_node = dev_node_path.BaseName().value();
+  if (event_node.empty() ||
+      !StartsWithASCII(event_node, "event", false)) {
+    return false;
+  }
+
+  // Extract id "XXX" from "eventXXX"
+  std::string event_node_id = event_node.substr(5);
+
+  // I2C input device registers its dev input node at
+  // /sys/bus/i2c/devices/*/input/inputXXX/eventXXX
+  FileEnumerator i2c_enum(FilePath(FILE_PATH_LITERAL("/sys/bus/i2c/devices/")),
+                          false,
+                          base::FileEnumerator::DIRECTORIES);
+  for (FilePath i2c_name = i2c_enum.Next();
+       !i2c_name.empty();
+       i2c_name = i2c_enum.Next()) {
+    FileEnumerator input_enum(i2c_name.Append(FILE_PATH_LITERAL("input")),
+                              false,
+                              base::FileEnumerator::DIRECTORIES,
+                              FILE_PATH_LITERAL("input*"));
+    for (base::FilePath input = input_enum.Next();
+         !input.empty();
+         input = input_enum.Next()) {
+      if (input.BaseName().value().substr(5) == event_node_id)
+        return true;
+    }
+  }
+
+  return false;
+}
+
+}  // namespace
+
 namespace ui {
 
 TouchscreenDeviceManagerX11::TouchscreenDeviceManagerX11()
@@ -70,8 +149,10 @@
     // Touchscreens should have absolute X and Y axes, and be direct touch
     // devices.
     if (width > 0.0 && height > 0.0 && is_direct_touch) {
+      bool is_internal = IsTouchscreenInternal(display_, info[i].deviceid);
       devices.push_back(TouchscreenDevice(info[i].deviceid,
-                                          gfx::Size(width, height)));
+                                          gfx::Size(width, height),
+                                          is_internal));
     }
   }
 
diff --git a/ui/display/types/chromeos/touchscreen_device.cc b/ui/display/types/chromeos/touchscreen_device.cc
index 09ee885..714b8f9 100644
--- a/ui/display/types/chromeos/touchscreen_device.cc
+++ b/ui/display/types/chromeos/touchscreen_device.cc
@@ -9,8 +9,11 @@
 // static
 const int TouchscreenDevice::kInvalidId = 0;
 
-TouchscreenDevice::TouchscreenDevice(int id, const gfx::Size& size)
+TouchscreenDevice::TouchscreenDevice(int id,
+                                     const gfx::Size& size,
+                                     bool is_internal)
     : id(id),
-      size(size) {}
+      size(size),
+      is_internal(is_internal) {}
 
 }  // namespace ui
diff --git a/ui/display/types/chromeos/touchscreen_device.h b/ui/display/types/chromeos/touchscreen_device.h
index ecc6452..3a471fa 100644
--- a/ui/display/types/chromeos/touchscreen_device.h
+++ b/ui/display/types/chromeos/touchscreen_device.h
@@ -14,13 +14,16 @@
 struct DISPLAY_TYPES_EXPORT TouchscreenDevice {
   static const int kInvalidId;
 
-  TouchscreenDevice(int id, const gfx::Size& size);
+  TouchscreenDevice(int id, const gfx::Size& size, bool is_internal);
 
   // ID of the touch screen. This ID must uniquely identify the touch screen.
   int id;
 
   // Size of the touch screen area.
   gfx::Size size;
+
+  // True if this is an internal touchscreen.
+  bool is_internal;
 };
 
 }  // namespace ui
diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc
index fb5e177..670de4d 100644
--- a/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/ui/views/accessibility/native_view_accessibility_win.cc
@@ -30,9 +30,6 @@
 namespace views {
 namespace {
 
-// A version of the OBJID_CLIENT constant that works in 64-bit mode too.
-static const LPARAM kObjIdClient = static_cast<ULONG>(OBJID_CLIENT);
-
 class AccessibleWebViewRegistry {
  public:
   static AccessibleWebViewRegistry* GetInstance();
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 60458c7..1a45795 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -932,6 +932,11 @@
     desktop_window_tree_host_->OnRootViewLayout();
 }
 
+bool DesktopNativeWidgetAura::IsTranslucentWindowOpacitySupported() const {
+  return content_window_ &&
+      desktop_window_tree_host_->IsTranslucentWindowOpacitySupported();
+}
+
 void DesktopNativeWidgetAura::RepostNativeEvent(gfx::NativeEvent native_event) {
   OnEvent(native_event);
 }
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index f265814..f005f36 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -178,6 +178,7 @@
   virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
   virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
   virtual void OnRootViewLayout() const OVERRIDE;
+  virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
   virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
 
   // Overridden from aura::WindowDelegate:
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index 26925b6..9ccb672 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -153,6 +153,9 @@
   // Returns true if the Widget was closed but is still showing because of
   // animations.
   virtual bool IsAnimatingClosed() const = 0;
+
+  // Returns true if the Widget supports translucency.
+  virtual bool IsTranslucentWindowOpacitySupported() const = 0;
 };
 
 }  // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index fc2bda6..6347526 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -365,7 +365,7 @@
 }
 
 bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
-  return ui::win::IsAeroGlassEnabled();
+  return IsTranslucentWindowOpacitySupported();
 }
 
 bool DesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent() const {
@@ -427,6 +427,10 @@
   return pending_close_;
 }
 
+bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const {
+  return ui::win::IsAeroGlassEnabled();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostWin, WindowTreeHost implementation:
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 5fb0639..225365f 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -103,6 +103,7 @@
   virtual void OnNativeWidgetFocus() OVERRIDE;
   virtual void OnNativeWidgetBlur() OVERRIDE;
   virtual bool IsAnimatingClosed() const OVERRIDE;
+  virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
 
   // Overridden from aura::WindowTreeHost:
   virtual ui::EventSource* GetEventSource() OVERRIDE;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index e7d86b5..74026c1 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -831,6 +831,10 @@
   return false;
 }
 
+bool DesktopWindowTreeHostX11::IsTranslucentWindowOpacitySupported() const {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostX11, aura::WindowTreeHost implementation:
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index cbcd9fc..cee65f5 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -144,6 +144,7 @@
   virtual void OnNativeWidgetFocus() OVERRIDE;
   virtual void OnNativeWidgetBlur() OVERRIDE;
   virtual bool IsAnimatingClosed() const OVERRIDE;
+  virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
 
   // Overridden from aura::WindowTreeHost:
   virtual ui::EventSource* GetEventSource() OVERRIDE;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index e26c52c..a1f05c4 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -691,6 +691,10 @@
 void NativeWidgetAura::OnRootViewLayout() const {
 }
 
+bool NativeWidgetAura::IsTranslucentWindowOpacitySupported() const {
+  return true;
+}
+
 void NativeWidgetAura::RepostNativeEvent(gfx::NativeEvent native_event) {
   OnEvent(native_event);
 }
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index 3b1e58a..dd6fafe 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -132,6 +132,7 @@
   virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
   virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
   virtual void OnRootViewLayout() const OVERRIDE;
+  virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
   virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
 
   // Overridden from views::InputMethodDelegate:
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h
index 0cd87b7..64cb9a3 100644
--- a/ui/views/widget/native_widget_mac.h
+++ b/ui/views/widget/native_widget_mac.h
@@ -102,6 +102,7 @@
   virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
   virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
   virtual void OnRootViewLayout() const OVERRIDE;
+  virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
   virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
 
  private:
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index 729207a..37545b9 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -359,6 +359,10 @@
   NOTIMPLEMENTED();
 }
 
+bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
+  return false;
+}
+
 void NativeWidgetMac::RepostNativeEvent(gfx::NativeEvent native_event) {
   NOTIMPLEMENTED();
 }
diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h
index d87bb0f..8c9233a 100644
--- a/ui/views/widget/native_widget_private.h
+++ b/ui/views/widget/native_widget_private.h
@@ -227,6 +227,7 @@
   virtual void SetVisibilityChangedAnimationsEnabled(bool value) = 0;
   virtual ui::NativeTheme* GetNativeTheme() const = 0;
   virtual void OnRootViewLayout() const = 0;
+  virtual bool IsTranslucentWindowOpacitySupported() const = 0;
 
   // Repost an unhandled event to the native widget for default OS processing.
   virtual void RepostNativeEvent(gfx::NativeEvent native_event) = 0;
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index fdcb32a..3f4a170 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -981,6 +981,10 @@
   native_widget_->OnRootViewLayout();
 }
 
+bool Widget::IsTranslucentWindowOpacitySupported() const {
+  return native_widget_->IsTranslucentWindowOpacitySupported();
+}
+
 void Widget::OnOwnerClosing() {
 }
 
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index bc3f914..c76633b 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -198,6 +198,9 @@
     WidgetDelegate* delegate;
     bool child;
     // If TRANSLUCENT_WINDOW, the widget may be fully or partially transparent.
+    // Translucent windows may not always be supported. Use
+    // IsTranslucentWindowOpacitySupported to determine if translucent windows
+    // are supported.
     // If OPAQUE_WINDOW, we can perform optimizations based on the widget being
     // fully opaque.  Defaults to TRANSLUCENT_WINDOW if
     // ViewsDelegate::UseTransparentWindows().  Defaults to OPAQUE_WINDOW for
@@ -726,6 +729,9 @@
   // window sizing information to the window server on some platforms.
   void OnRootViewLayout();
 
+  // Whether the widget supports translucency.
+  bool IsTranslucentWindowOpacitySupported() const;
+
   // Notification that our owner is closing.
   // NOTE: this is not invoked for aura as it's currently not needed there.
   // Under aura menus close by way of activation getting reset when the owner
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index d6ab099..d606206 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -623,6 +623,7 @@
     widget->ReleaseCapture();
     widget->HasCapture();
     widget->GetWorkAreaBoundsInScreen();
+    widget->IsTranslucentWindowOpacitySupported();
   }
 
  private:
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index e4f55bf..adbe4fa 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -45,9 +45,6 @@
 namespace views {
 namespace {
 
-// A version of the OBJID_CLIENT constant that works in 64-bit mode too.
-static const LPARAM kObjIdClient = static_cast<ULONG>(OBJID_CLIENT);
-
 // MoveLoopMouseWatcher is used to determine if the user canceled or completed a
 // move. win32 doesn't appear to offer a way to determine the result of a move,
 // so we install hooks to determine if we got a mouse up and assume the move
@@ -1419,8 +1416,12 @@
                                         LPARAM l_param) {
   LRESULT reference_result = static_cast<LRESULT>(0L);
 
+  // Only the lower 32 bits of l_param are valid when checking the object id
+  // because it sometimes gets sign-extended incorrectly (but not always).
+  DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param));
+
   // Accessibility readers will send an OBJID_CLIENT message
-  if (kObjIdClient == l_param) {
+  if (OBJID_CLIENT == obj_id) {
     // Retrieve MSAA dispatch object for the root view.
     base::win::ScopedComPtr<IAccessible> root(
         delegate_->GetNativeViewAccessible());